6
2

More than 5 years have passed since last update.

rails c で開発中のアプリに簡単なhttpリクエストを送る時に気をつけたことメモ

Last updated at Posted at 2018-02-23

ちょっとリクエストを送る時に詰まったことがあるので一応共有させていただきます.

参考にさせていただいた記事

rails console で Controller を呼ぶ際のtips

環境

$ ruby -v
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-linux]

やって見たこと

最近railsでapiを作ることがあったのですが、開発をしている時にちょっと動作確認をしたいなとなり、調べて見たところrails c内でhttpリクエストを実行できるメソッドを発見しました

app.get '/foo', {httpパラメータ}, {http header}

早速使ってみると….

[1] pry(main)> app.get '/foo', { page: 4 }, {'HTTP_HEADER' => "header_val"}
ArgumentError: wrong number of arguments (given 3, expected 1)
from /usr/local/bundle/gems/actionpack-5.1.4/lib/action_dispatch/testing/integration.rb:15:in `get'

なぜか引数の数が合わない…

参考にさせていただいたサンプルだとメソッドの引数は可変長引数みたいですが私の環境だと違うみたいです.

これ以上調べても何も出てこなかったので実際にgetメソッドの中身を見てみました

    15        def get(path, **args)
    16          process(:get, path, **args)
    17        end

argsが可変長引数ではなくhashを受け取るようになっていますね

ですがhashとはいっても内部構造をきちんと考えないといけません

processメソッドの中身を見てみます


     #   process :get, '/author', params: { since: 201501011400 }
      def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
        request_encoder = RequestEncoder.encoder(as)
        headers ||= {}

        if method == :get && as == :json && params
          headers["X-Http-Method-Override"] = "GET"
          method = :post
        end

        if path =~ %r{://}
          path = build_expanded_path(path) do |location|
            https! URI::HTTPS === location if location.scheme

            if url_host = location.host
              default = Rack::Request::DEFAULT_PORTS[location.scheme]
              url_host += ":#{location.port}" if default != location.port
              host! url_host
            end
          end
        end

        hostname, port = host.split(":")

        request_env = {
          :method => method,
          :params => request_encoder.encode_params(params),

          "SERVER_NAME"     => hostname,
          "SERVER_PORT"     => port || (https? ? "443" : "80"),
          "HTTPS"           => https? ? "on" : "off",
          "rack.url_scheme" => https? ? "https" : "http",

          "REQUEST_URI"    => path,
          "HTTP_HOST"      => host,
          "REMOTE_ADDR"    => remote_addr,
          "CONTENT_TYPE"   => request_encoder.content_type,
          "HTTP_ACCEPT"    => request_encoder.accept_header || accept
        }

        wrapped_headers = Http::Headers.from_hash({})
        wrapped_headers.merge!(headers) if headers

        if xhr
          wrapped_headers["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
          wrapped_headers["HTTP_ACCEPT"] ||= [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ")
        end

        # this modifies the passed request_env directly
        if wrapped_headers.present?
          Http::Headers.from_hash(request_env).merge!(wrapped_headers)
        end
        if env.present?
          Http::Headers.from_hash(request_env).merge!(env)
        end

        session = Rack::Test::Session.new(_mock_session)

        # NOTE: rack-test v0.5 doesn't build a default uri correctly
        # Make sure requested path is always a full uri
        session.request(build_full_uri(path, request_env), request_env)

        @request_count += 1
        @request = ActionDispatch::Request.new(session.last_request.env)
        response = _mock_session.last_response
        @response = ActionDispatch::TestResponse.from_response(response)
        @response.request = @request
        @html_document = nil
        @url_options = nil

        @controller = @request.controller_instance

        response.status
      end

見たところhttpパラメータはparams, headerはheadersとなっているようです

これらのことからうまい具合に調整してリクエストを投げて見ました


[1] pry(main)> app.get '/foo', {
  params: { page: 4 },
  headers: {'HTTP_HEADER' => "header_val"}
}

リクエストが通りました

まだまだ至らない点もありますので、何か誤り等ありましたらご指摘いただけると幸いです

補足

私が過去に作ったapiでもgetメソッドを調べて見たところこうなりました
rubyのバージョンは以下の通りです

ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]

/usr/local/bundle/gems/actionpack-5.0.ore/lib/action_dispatch/testing/integration.rb
module ActionDispatch
  module Integration #:nodoc:
    module RequestHelpers
      def get(path, *args)
        process_with_kwargs(:get, path, *args)
      end

どうやらactionpackのバージョンにズレがあったのが原因みたいです

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2