soveran / syro

Simple router for web applications

Home Page:http://soveran.github.io/syro/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Accessing Request Headers

moonglum opened this issue Β· comments

Syro has an easy way to set and get response headers:

res.headers["Content-Type"]

When it comes to request headers though, there is only the weird way that Rack provides (after it changed the name of the request header by upcasing it and replacing - with _):

req.env['HTTP_ACCEPT_CHARSET'] # reads the 'Accept-Charset' header

What do you think about providing a way of accessing the request headers similar to the way you provide access to the response headers? Something like this:

req.headers['Accept-Charset']

We discussed this for Tynn in frodsan/tynn#17, but I was wondering if this is not a feature on "Syro Level" πŸ˜‰

Hey @moonglum, very interesting topic! I read the conversation in the reference, but I couldn't check any code yet as I don't have access to my computer right now.

Check if you can if that transformation is part of an RFC or something. I believe it is, and I can check later if you don't have time now.

Apart from that, this question makes me think about some very different approaches worth discussing, depending on the direction we think is best for the project. For example, should Syro attempt to be used standalone? If yes, then we can consider the merits of that feature. Should it be only a building block for web frameworks? Then maybe it should offer the minimum to avoid pushing design decisions downstream. A bit of both? Then we can think about where to draw the line for it to be useful while leaving the options open for the implementers.

If you can, let me know what you think! I should be able to investigate more later today or tomorrow morning.

Check if you can if that transformation is part of an RFC or something. I believe it is, and I can check later if you don't have time now.

I'm away from the computer until Sunday, but I can check back in detail on Monday πŸ˜„

For example, should Syro attempt to be used standalone? Should it be only a building block for web frameworks? A bit of both?

My current opinion on this (and I'm always happy to change it), is that Syro should be a building block. For me a very interesting part of Syro is extensibility, and I think @frodsan enhanced this even further in Tynn. I think that a framework like Tynn should just be a collection of extensions that do not need to rewrite parts of Syro. This is why I like the idea of decks:
There can be a deck specialized on creating JSON APIs which probably doesn't need a way to render HTML, and a deck for websites maybe doesn't need a JSON parsing function. Through the idea of useing another Syro app, they can then be combined if that's required.

Yes, I agree with you. I like the idea of it being a building block that Tynn can specialize. I'll check this issue tomorrow. Thanks!

A few thoughts I had before falling asleep last night:

  • I think that the defining feature of Syro is the routing tree, which makes it part of the Rum family. It is special, as it tears down the arbitrary wall between "router" and "controller", where the line between them is never quite clear. For Syro the line is clear: I handle HTTP for you! That means handling all aspects of the request and the response.
  • A library or framework built on top of Syro needs to agree to the premise of routing trees.
  • Syro should (and does) make it easy to extend it.
    • Syro supports Decks incl. default headers, custom request and response classes for customizations
    • Tynn adds middlewares and plugins for further customization and offers a set of default middlewares and plugins for selection by the user.

Check if you can if that transformation is part of an RFC or something. I believe it is, and I can check later if you don't have time now.

I found this: https://tools.ietf.org/html/rfc3875#section-4.1.18 and https://github.com/rack/rack/blob/028438ffffd95ce1f6197d38c04fa5ea6a034a85/lib/rack/lint.rb#L117

CGI!

OK, it means we shouldn't modify it, right? Should we close this issue?

Interesting. Reaaally interesting. Thanks πŸ˜„

Yes, I agree with closing this. I think that Syro fixes a weird Rack-ism, where the Request has its own class, but the response is a three element tuple (consisting of status, header and body) by replacing the tuple with a class. It therefore makes sense that it has accessors for each of its elements:

  • status: status & status=
  • body: body & write
  • headers: headers, [], []=

I think that makes sense given the different nature of each of those. But why did you decide to include redirect, set_cookie and get_cookie? Maybe that should move to a higher level (aka. Tynn and similar projects).

I think Syro could also depend only on env, pushing downstream the complexity of querying the request and building the response, but at this point I think it's better to keep it usable by providing a basic set of features for building a "hello world" app, or an API, or in general anything simple for which it could be used directly.

Agreed!

Just out of curiosity: Why did you decide to not use Rack::Response, but instead writing your own version and on the other hand use Rack::Request? Both seem to be doing a lot.

The reason for that comes from a benchmark we did with Cuba a long time ago, where we were able to improve the performance we were getting with Rack::Response. But Rack::Request was not so easy to replace because its API is bigger. Just to add to my previous comment: that vision is not final, and I will keep investigating what's the minimal feature set that makes sense.

Thanks for explaining it πŸ™‡

@moonglum I made a benchmark: https://gist.github.com/frodsan/a1e9a8b25f67e384a4d0

Syro::Response returns a body as an array, Rack::Response returns a class :?

[200, {"Content-Length"=>"11", "Content-Type"=>"text/html"}, ["Hello World"]]
[200, {"Content-Length"=>"11"}, #<Rack::BodyProxy:0x007fa1c99e0cb0 ...>

Woha oO That's a HUGE difference 😲

@moonglum, @frodsan, should we remove set_cookie and delete_cookie? I've only used them once in the past, and removing them would mean users would have to use something like this:

Rack::Utils.set_cookie_header!(req.headers, key, value)

Another idea is to rework the API and have a class Cookies to abstract that code. I think for now removing those two methods should be fine. Thoughts?

πŸ‘ to remove them. They're not signed/encrypted, I think a framework using Syro can add support for that.

πŸ‘ to remove them. I also see that on a "Tynn" Level (Tynn being a stand-in for similar libs). In addition to what @frodsan said: There could be a Syro-based lib for creating JSON APIs where the APIs use tokens instead of cookies. It would have no need for cookies at all πŸ˜‰

@moonglum @frodsan Can you jump on IRC for a quick chat? I'm in #syro on Freenode