Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I pass POST payload? #56

Closed
Nakilon opened this issue May 24, 2021 · 4 comments
Closed

How do I pass POST payload? #56

Nakilon opened this issue May 24, 2021 · 4 comments

Comments

@Nakilon
Copy link

Nakilon commented May 24, 2021

I feel like I should set content-type header and somewhere between these lines

down/lib/down/http.rb

Lines 89 to 91 in 3a70e35

client = @client
client = client.basic_auth(user: uri.user, pass: uri.password) if uri.user || uri.password
client = block.call(client) if block

there should be

client.body = payload
@janko
Copy link
Owner

janko commented May 24, 2021

Passing form-encoded POST parameters can be done using the http.rb's :form option. Example:

require "down/http"
require "json"

io = Down::Http.open("https://httpbin.org/post", method: :post, form: { "foo" => "bar" })
JSON.parse(io.read)
# => {"args"=>{},
#     "data"=>"",
#     "files"=>{},
#     "form"=>{"foo"=>"bar"},
#     "headers"=>
#      {"Content-Length"=>"7",
#       "Content-Type"=>"application/x-www-form-urlencoded",
#       "Host"=>"httpbin.org",
#       "User-Agent"=>"Down/5.2.1",
#       "X-Amzn-Trace-Id"=>"Root=1-60abf327-318b8db9456ae63260a21bc9"},
#     "json"=>nil,
#     "origin"=>"83.240.62.43",
#     "url"=>"https://httpbin.org/post"}

@janko janko closed this as completed May 24, 2021
@Nakilon
Copy link
Author

Nakilon commented May 25, 2021

Oh, and I see JSON example there too, thanks. Somehow couldn't find it neither in tests nor in the main README.

UPD: ah sure, because that's another gem...

@Nakilon
Copy link
Author

Nakilon commented May 25, 2021

So I've got 411 Length Required (Down::ClientError). Passing "Content-Length" header didn't help, so I started a fake server to inspect the requests:

require "webrick"
require "pp"
WEBrick::HTTPServer.new(Port: 8080).tap{ |s|
  s.mount_proc("/"){ |req, res|
    pp req.header; res.body = "1"*1000 + "2"*2000
  }
}.start
require "down/http"
json = JSON.dump input
Down::Http.download(
  "http://localhost:8080/",
  headers: {
    "Authorization" => "bearer 123}",
    "Content-Length" => json.size
  },
  method: :post, body: json, max_size: 1000
).read

But it throws file is too large (max is 0MB) (Down::TooLarge) and I see no way to get those "first 1000 bytes" that I need. So maybe the down gem wasn't supposed to do such thing in the first place and I'm in the dead end? I just wanted to limit the download size.

UPD: I'll start it as another ticket if needed.

@jrochkind
Copy link
Collaborator

jrochkind commented May 25, 2021

I don't think setting content-length on an HTTP request does what you think it does, just in terms of the HTTP protocol. I don't think you are encountering a bug in down. Also I don't think this is about passing a POST payload anymore?

If you want to download only the first 1000 bytes of a server response, my ideas would be to try to use HTTP Range headers (assuming the server supports this), or you can perhaps use down's streaming API to only read the first 1000 bytes, and discard the rest.

Setting content-length in a request is not a way to do what you want, that is not how it works according to the HTTP protocol. Content-length on a request must be the size of the request body. This is not about down, just about the HTTP protocol. Also, how to download only first 1000 bytes of a response is a different question than passing a POST payload, no?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants