Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@TakutoOooka

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

More than 3 years have passed since last update.

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

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

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のバージョンにズレがあったのが原因みたいです

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?