diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index c40b74ece8d0..7094d67cb061 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -1080,7 +1080,9 @@ Z = erlang:crc32_combine(X,Y,iolist_size(Data2)). as atoms. Others are returned as strings. Strings of unrecognized header fields are formatted with only capital letters first and after hyphen characters, for - example, "Sec-Websocket-Key".

+ example, "Sec-Websocket-Key". Header field names + are also returned in UnmodifiedField + as strings, without any conversion or formatting.

The protocol type http is only to be used for the first line when an HttpRequest or an HttpResponse is expected. diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 17e09f835b68..cf633b2f0145 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -1228,22 +1228,25 @@ static int http_request_erl(void* arg, const http_atom_t* meth, } static int -http_header_erl(void* arg, const http_atom_t* name, const char* name_ptr, - int name_len, const char* value_ptr, int value_len) +http_header_erl(void* arg, const http_atom_t* name, + const char* name_ptr, int name_len, + const char* oname_ptr, int oname_len, + const char* value_ptr, int value_len) { struct packet_callback_args* pca = (struct packet_callback_args*) arg; - Eterm bit_term, name_term, val_term; + Eterm bit_term, name_term, oname_term, val_term; Uint sz = 6; Eterm* hp; #ifdef DEBUG Eterm* hend; #endif - /* {http_header,Bit,Name,IValue,Value} */ + /* {http_header,Bit,Name,Oname,Value} */ if (name == NULL) { http_bld_string(pca, NULL, &sz, name_ptr, name_len); } + http_bld_string(pca, NULL, &sz, oname_ptr, oname_len); http_bld_string(pca, NULL, &sz, value_ptr, value_len); hp = HAlloc(pca->p, sz); @@ -1260,8 +1263,9 @@ http_header_erl(void* arg, const http_atom_t* name, const char* name_ptr, name_term = http_bld_string(pca, &hp,NULL,name_ptr,name_len); } + oname_term = http_bld_string(pca, &hp, NULL, oname_ptr, oname_len); val_term = http_bld_string(pca, &hp, NULL, value_ptr, value_len); - pca->res = TUPLE5(hp, am_http_header, bit_term, name_term, am_undefined, val_term); + pca->res = TUPLE5(hp, am_http_header, bit_term, name_term, oname_term, val_term); ASSERT(hp+6==hend); return 1; } diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c index c0937aa5f24a..8f24725326e7 100644 --- a/erts/emulator/beam/packet_parser.c +++ b/erts/emulator/beam/packet_parser.c @@ -834,7 +834,9 @@ int packet_parse_http(const char* buf, int len, int* statep, while (n && SP(ptr)) { ptr++; n--; } - return pcb->http_header(arg, name, name_ptr, name_len, + return pcb->http_header(arg, name, + name_ptr, name_len, + buf, name_len, ptr, n); } return -1; diff --git a/erts/emulator/beam/packet_parser.h b/erts/emulator/beam/packet_parser.h index 358d650804e0..b05623efec84 100644 --- a/erts/emulator/beam/packet_parser.h +++ b/erts/emulator/beam/packet_parser.h @@ -77,8 +77,10 @@ typedef int HttpResponseMessageFn(void* arg, int major, int minor, int status, typedef int HttpRequestMessageFn(void* arg, const http_atom_t* meth, const char* meth_ptr, int meth_len, const PacketHttpURI*, int major, int minor); typedef int HttpEohMessageFn(void *arg); -typedef int HttpHeaderMessageFn(void* arg, const http_atom_t* name, const char* name_ptr, - int name_len, const char* value_ptr, int value_len); +typedef int HttpHeaderMessageFn(void* arg, const http_atom_t* name, + const char* name_ptr, int name_len, + const char* oname_ptr, int oname_len, + const char* value_ptr, int value_len); typedef int HttpErrorMessageFn(void* arg, const char* buf, int len); typedef int SslTlsFn(void* arg, unsigned type, unsigned major, unsigned minor, const char* data, int len, const char* prefix, int plen); diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 66ff8d84504c..8c10aa99334c 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -2574,16 +2574,18 @@ http_request_inetdrv(void* arg, const http_atom_t* meth, const char* meth_ptr, } static int -http_header_inetdrv(void* arg, const http_atom_t* name, const char* name_ptr, - int name_len, const char* value_ptr, int value_len) +http_header_inetdrv(void* arg, const http_atom_t* name, + const char* name_ptr, int name_len, + const char* oname_ptr, int oname_len, + const char* value_ptr, int value_len) { tcp_descriptor* desc = (tcp_descriptor*) arg; int i = 0; - ErlDrvTermData spec[26]; + ErlDrvTermData spec[27]; ErlDrvTermData caller = ERL_DRV_NIL; if (desc->inet.active == INET_PASSIVE) { - /* {inet_async,S,Ref,{ok,{http_header,Bit,Name,IValue,Value}} */ + /* {inet_async,S,Ref,{ok,{http_header,Bit,Name,Oname,Value}} */ int req; int aid; @@ -2596,7 +2598,7 @@ http_header_inetdrv(void* arg, const http_atom_t* name, const char* name_ptr, i = LOAD_ATOM(spec, i, am_ok); } else { - /* {http, S, {http_header,Bit,Name,IValue,Value}} */ + /* {http, S, {http_header,Bit,Name,Oname,Value}} */ i = LOAD_ATOM(spec, i, am_http); i = LOAD_PORT(spec, i, desc->inet.dport); } @@ -2610,19 +2612,19 @@ http_header_inetdrv(void* arg, const http_atom_t* name, const char* name_ptr, i = LOAD_INT(spec, i, 0); i = http_load_string(desc, spec, i, name_ptr, name_len); } - i = LOAD_ATOM(spec, i, am_undefined); + i = http_load_string(desc, spec, i, oname_ptr, oname_len); i = http_load_string(desc, spec, i, value_ptr, value_len); i = LOAD_TUPLE(spec, i, 5); if (desc->inet.active == INET_PASSIVE) { i = LOAD_TUPLE(spec, i, 2); i = LOAD_TUPLE(spec, i, 4); - ASSERT(i <= 26); + ASSERT(i <= 27); return erl_drv_send_term(desc->inet.dport, caller, spec, i); } else { i = LOAD_TUPLE(spec, i, 3); - ASSERT(i <= 26); + ASSERT(i <= 27); return erl_drv_output_term(desc->inet.dport, spec, i); } } diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl index d0f46167e426..099dfabcb686 100644 --- a/erts/emulator/test/decode_packet_SUITE.erl +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -301,8 +301,8 @@ http(Config) when is_list(Config) -> StrA = list_to_atom(Str), StrB = list_to_binary(Str), Bin = <>, - {ok, {http_header,N,StrA,undefined,Val}, Rest} = decode_pkt(httph,Bin), - {ok, {http_header,N,StrA,undefined,ValB}, Rest} = decode_pkt(httph_bin,Bin), + {ok, {http_header,N,StrA,Str,Val}, Rest} = decode_pkt(httph,Bin), + {ok, {http_header,N,StrA,StrB,ValB}, Rest} = decode_pkt(httph_bin,Bin), N + 1 end, lists:foldl(HdrF, 1, http_hdr_strings()), @@ -373,28 +373,40 @@ http_request(Msg) -> {http_request, 'POST', {abs_path, "/invalid/url" }, {1,1}}, {http_request, 'POST', {abs_path,<<"/invalid/url">>}, {1,1}}}, {"Connection: close\r\n", - {http_header,2,'Connection',undefined, "close"}, - {http_header,2,'Connection',undefined,<<"close">>}}, + {http_header,2,'Connection', "Connection" , "close"}, + {http_header,2,'Connection',<<"Connection">>,<<"close">>}}, {"User-Agent: perl post\r\n", - {http_header,24,'User-Agent',undefined, "perl post"}, - {http_header,24,'User-Agent',undefined,<<"perl post">>}}, + {http_header,24,'User-Agent', "User-Agent" , "perl post"}, + {http_header,24,'User-Agent',<<"User-Agent">>,<<"perl post">>}}, {"Content-Length: 4\r\n", - {http_header,38,'Content-Length',undefined, "4"}, - {http_header,38,'Content-Length',undefined,<<"4">>}}, + {http_header,38,'Content-Length', "Content-Length" , "4"}, + {http_header,38,'Content-Length',<<"Content-Length">>,<<"4">>}}, {"Content-Type: text/xml; charset=utf-8\r\n", - {http_header,42,'Content-Type',undefined, "text/xml; charset=utf-8"}, - {http_header,42,'Content-Type',undefined,<<"text/xml; charset=utf-8">>}}, + {http_header,42,'Content-Type', "Content-Type" , "text/xml; charset=utf-8"}, + {http_header,42,'Content-Type',<<"Content-Type">>,<<"text/xml; charset=utf-8">>}}, {"Other-Field: with some text\r\n", - {http_header,0, "Other-Field" ,undefined, "with some text"}, - {http_header,0,<<"Other-Field">>,undefined,<<"with some text">>}}, + {http_header,0, "Other-Field" , "Other-Field" , "with some text"}, + {http_header,0,<<"Other-Field">>,<<"Other-Field">>,<<"with some text">>}}, + {"Content--Type: text/xml; charset=utf-8\r\n", + {http_header,0, "Content--type" , "Content--Type" , "text/xml; charset=utf-8"}, + {http_header,0,<<"Content--type">>,<<"Content--Type">>,<<"text/xml; charset=utf-8">>}}, + {"Content---Type: text/xml; charset=utf-8\r\n", + {http_header,0, "Content---Type" , "Content---Type" , "text/xml; charset=utf-8"}, + {http_header,0,<<"Content---Type">>,<<"Content---Type">>,<<"text/xml; charset=utf-8">>}}, + {"CONTENT-type: text/xml; charset=utf-8\r\n", + {http_header,42,'Content-Type', "CONTENT-type" , "text/xml; charset=utf-8"}, + {http_header,42,'Content-Type',<<"CONTENT-type">>,<<"text/xml; charset=utf-8">>}}, + {"OTHER-field: with some text\r\n", + {http_header,0, "Other-Field" , "OTHER-field" , "with some text"}, + {http_header,0,<<"Other-Field">>,<<"OTHER-field">>,<<"with some text">>}}, {"Make-sure-a-LONG-HEaDer-fIeLd-is-fORMATTED-NicelY: with some text\r\n", - {http_header,0, "Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely" ,undefined, "with some text"}, - {http_header,0,<<"Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely">>,undefined,<<"with some text">>}}, + {http_header,0, "Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely" , "Make-sure-a-LONG-HEaDer-fIeLd-is-fORMATTED-NicelY" , "with some text"}, + {http_header,0,<<"Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely">>,<<"Make-sure-a-LONG-HEaDer-fIeLd-is-fORMATTED-NicelY">>,<<"with some text">>}}, {"Multi-Line: Once upon a time in a land far far away,\r\n" " there lived a princess imprisoned in the highest tower\r\n" " of the most haunted castle.\r\n", - {http_header,0, "Multi-Line" ,undefined, "Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle."}, - {http_header,0,<<"Multi-Line">>,undefined,<<"Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle.">>}}, + {http_header,0, "Multi-Line" , "Multi-Line" , "Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle."}, + {http_header,0,<<"Multi-Line">>,<<"Multi-Line">>,<<"Once upon a time in a land far far away,\r\n there lived a princess imprisoned in the highest tower\r\n of the most haunted castle.">>}}, {"\r\n", http_eoh, http_eoh}], @@ -410,17 +422,17 @@ http_response(Msg) -> {http_response, {1,0}, 404, "Object Not Found"}, {http_response, {1,0}, 404, <<"Object Not Found">>}}, {"Server: inets/4.7.16\r\n", - {http_header, 30, 'Server', undefined, "inets/4.7.16"}, - {http_header, 30, 'Server', undefined, <<"inets/4.7.16">>}}, + {http_header, 30, 'Server', "Server" , "inets/4.7.16"}, + {http_header, 30, 'Server', <<"Server">>, <<"inets/4.7.16">>}}, {"Date: Fri, 04 Jul 2008 17:16:22 GMT\r\n", - {http_header, 3, 'Date', undefined, "Fri, 04 Jul 2008 17:16:22 GMT"}, - {http_header, 3, 'Date', undefined, <<"Fri, 04 Jul 2008 17:16:22 GMT">>}}, + {http_header, 3, 'Date', "Date" , "Fri, 04 Jul 2008 17:16:22 GMT"}, + {http_header, 3, 'Date', <<"Date">>, <<"Fri, 04 Jul 2008 17:16:22 GMT">>}}, {"Content-Type: text/html\r\n", - {http_header, 42, 'Content-Type', undefined, "text/html"}, - {http_header, 42, 'Content-Type', undefined, <<"text/html">>}}, + {http_header, 42, 'Content-Type', "Content-Type" , "text/html"}, + {http_header, 42, 'Content-Type', <<"Content-Type">>, <<"text/html">>}}, {"Content-Length: 207\r\n", - {http_header, 38, 'Content-Length', undefined, "207"}, - {http_header, 38, 'Content-Length', undefined, <<"207">>}}, + {http_header, 38, 'Content-Length', "Content-Length" , "207"}, + {http_header, 38, 'Content-Length', <<"Content-Length">>, <<"207">>}}, {"\r\n", http_eoh, http_eoh}], @@ -548,7 +560,7 @@ otp_8536_do(N) -> Bin = <>, io:format("Bin='~p'\n",[Bin]), - {ok,{http_header,0,Hdr2,undefined,Data2},<<"\r\n">>} = decode_pkt(httph_bin, Bin, []), + {ok,{http_header,0,Hdr2,Hdr2,Data2},<<"\r\n">>} = decode_pkt(httph_bin, Bin, []), %% Do something to trash the C-stack, how about another decode_packet: decode_pkt(httph_bin,<>, []), diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 869982c262f4..2c5b24ef7064 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -630,7 +630,7 @@ date() -> HttpHeader :: {'http_header', integer(), HttpField, - Reserved :: term(), + UnmodifiedField :: HttpString, Value :: HttpString}, HttpError :: {'http_error', HttpString}, HttpMethod :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index b79a51f02a61..03e77dd8633f 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -1130,7 +1130,7 @@ server_send_trailer(Socket, Trailer)-> client_http_decode_trailer_active(Socket) -> receive {ssl, Socket, - {http_header,36,'Content-Encoding',undefined,"gzip"}} -> + {http_header,36,'Content-Encoding',"Content-Encoding","gzip"}} -> ok; Other1 -> exit({?LINE, Other1}) @@ -1180,7 +1180,7 @@ packet_httph_bin_active(Config) when is_list(Config) -> client_http_decode_trailer_bin_active(Socket) -> receive {ssl, Socket, - {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} -> + {http_header,36,'Content-Encoding',<<"Content-Encoding">>, <<"gzip">>}} -> ok; Other1 -> exit({?LINE, Other1}) @@ -1232,7 +1232,7 @@ client_http_decode_trailer_active_once(Socket) -> ssl:setopts(Socket, [{active, once}]), receive {ssl, Socket, - {http_header,36,'Content-Encoding',undefined,"gzip"}} -> + {http_header,36,'Content-Encoding',"Content-Encoding","gzip"}} -> ok; Other1 -> exit({?LINE, Other1}) @@ -1284,7 +1284,7 @@ client_http_decode_trailer_bin_active_once(Socket) -> ssl:setopts(Socket, [{active, once}]), receive {ssl, Socket, - {http_header,36,'Content-Encoding',undefined, <<"gzip">>}} -> + {http_header,36,'Content-Encoding',<<"Content-Encoding">>, <<"gzip">>}} -> ok; Other1 -> exit({?LINE, Other1}) @@ -1335,7 +1335,7 @@ packet_httph_passive(Config) when is_list(Config) -> ssl_test_lib:close(Client). client_http_decode_trailer_passive(Socket) -> - {ok,{http_header,36,'Content-Encoding',undefined,"gzip"}} = ssl:recv(Socket, 0), + {ok,{http_header,36,'Content-Encoding',"Content-Encoding","gzip"}} = ssl:recv(Socket, 0), {ok, http_eoh} = ssl:recv(Socket, 0), ok. @@ -1375,7 +1375,7 @@ packet_httph_bin_passive(Config) when is_list(Config) -> ssl_test_lib:close(Client). client_http_decode_trailer_bin_passive(Socket) -> - {ok,{http_header,36,'Content-Encoding',undefined,<<"gzip">>}} = ssl:recv(Socket, 0), + {ok,{http_header,36,'Content-Encoding',<<"Content-Encoding">>,<<"gzip">>}} = ssl:recv(Socket, 0), {ok, http_eoh} = ssl:recv(Socket, 0), ok.