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

Add form data shortcut method to HTTP::Request #9941

Open
Blacksmoke16 opened this issue Nov 20, 2020 · 4 comments
Open

Add form data shortcut method to HTTP::Request #9941

Blacksmoke16 opened this issue Nov 20, 2020 · 4 comments

Comments

@Blacksmoke16
Copy link
Member

Blacksmoke16 commented Nov 20, 2020

HTTP::Request currently has a #query_params method that lazily loads an HTTP::Params object based on the request's query string. Thoughts on doing something similar for the requests' form data?

The problem without this is that you have to consume the body IO in order create the HTTP::Params object, making it impossible to access the data again in a different context without exposing the original params object somehow.

@jhass
Copy link
Member

jhass commented Nov 20, 2020

Which body IO needs to be consumed in a HTTP::Request context here? 😕

@Blacksmoke16
Copy link
Member Author

Blacksmoke16 commented Nov 20, 2020

@jhass The form data is included in the request body. So like to do this currently you have to do:

params = HTTP::Params.parse(request.body.not_nil!.gets_to_end)

However once you do this you can't rewind request.body, so aren't able to directly access the form data in another context, say another HTTP::Handler.

@jhass
Copy link
Member

jhass commented Nov 20, 2020

But a helper method could not magically solve that. Not without making it way to easy to read way too much data into memory, think file-uploads.

Also the big big difference is that any request URL always has query params implicitly, they just may be empty. This is not the case at all with an application/x-www-form-urlencoded request body, so this would easily introduce more potential runtime errors where people don't check before using the method. In #9901 we're currently discussing a way to reduce these kinds of confusions and runtime errors, readding a new class of confusion and easy to make mistakes with this proposal seems quite counter-productive.

@Blacksmoke16
Copy link
Member Author

Blacksmoke16 commented Nov 20, 2020

@jhass For the query param method we just return an empty HTTP::Params instance if there are none. I was imagining we do something similar here. I.e. if there is no body or its empty, return an empty params object. Granted this would still result in errors if someone uses it and tries to access a param that doesn't exist, but that's not really different than the current behavior. I guess the major downside of having this is not knowing whats in the request body when calling the method.

I'm open to other suggestions as well. My use case is I have a series of Param types that have a parse_value(request : HTTP::Request) method to extract a related parameter from the request. Currently this works fine for query params but only allows for the first form data because when the others go to read it, the body IO is empty. I'm currently adding in a method like this for that context:

@form_data : HTTP::Params?

def form_data : HTTP::Params
  @form_data ||= self.parse_form_data
end

private def parse_form_data : HTTP::Params
  HTTP::Params.parse self.body.try(&.gets_to_end) || ""
end

🤷.

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

No branches or pull requests

3 participants