CrowdHailer / Ace

HTTP web server and client, supports http1 and http2

Home Page:https://hex.pm/packages/ace

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Key already defined error

samsondav opened this issue · comments

commented

Yesterday we suddenly started seeing a lot of these in production:

Elixir.MatchError: no match of right hand side value: {:error, {:key_already_defined_as, "format"}}
  File "lib/ace/http1/parser.ex", line 226, in Ace.HTTP1.Parser.build_partial_request/2
  File "lib/ace/http1/parser.ex", line 130, in Ace.HTTP1.Parser.pop_part/1
  File "lib/ace/http1/parser.ex", line 49, in Ace.HTTP1.Parser.parse/3
  File "lib/ace/http1/endpoint.ex", line 27, in Ace.HTTP1.Endpoint.handle_info/2
  File "gen_server.erl", line 616, in :gen_server.try_dispatch/4
  File "gen_server.erl", line 686, in :gen_server.handle_msg/6
  File "gen_server.erl", line 636, in :gen_server.try_handle_call/4
  File "gen_server.erl", line 665, in :gen_server.handle_msg/6
  Module "Elixir.Ace.HTTP.Server", in Ace.HTTP.Server.init/1

Any clue?

This can be reproduced by hitting a URL where a parameter is dulplicated, for example ?foo=a&foo=b, which falls through to this section of code in Raxx

The current behaviour is that this blows up, but the problem we have is that we will fail serving requests when third parties make mistakes. There's definitely an argument for that being the correct behaviour, but it might be useful to make this configurable, as there may be use cases where you just want to take the last value passed or treat it as a List (for example).

There's a relevant SO question which points out there is no defined standard for what should be done here, so for Raxx it might be sensible to make this configurable.

Happy to help in making this configurable if that's an acceptable solution?

This has been raised in Ace as that's where we've initially seen the issue, should we move this over to Raxx?

Thanks for the context @seddy

I hadn't realised the nuances involved with query strings when I started raxx. There is also the question of handling nested queries or not? None of this is specified in https://tools.ietf.org/html/rfc7230.

I think the correct behaviour is for Raxx not to specify query parsing.
So my suggestion is as follows:

  • example.com/ has query nil
  • example.com/? has query ""
  • example.com/?anything has query "anything"

I would then also add a fetch_query function to raxx

Raxx.fetch_query(request) returns {:ok, map} or {:error, :malformed_query}

If anyone wanted to tackle this I think to get started all that is needed is to remove calls to URI2 and then add the function described above.

Fixed in versions 0.16.x