From 0fc5f18b63576570b4a32be66093180d0fe814fb Mon Sep 17 00:00:00 2001 From: LuoJinghua Date: Tue, 27 Oct 2020 02:33:36 +0800 Subject: [PATCH] fix: Don't sort the headers of ClientRequest (#26134) --- shell/browser/api/electron_api_url_loader.cc | 2 +- shell/common/gin_converters/net_converter.h | 31 ++++++++++++++++++++ spec-main/api-net-spec.ts | 21 +++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/shell/browser/api/electron_api_url_loader.cc b/shell/browser/api/electron_api_url_loader.cc index 7f77346849e6..3cd7b96409eb 100644 --- a/shell/browser/api/electron_api_url_loader.cc +++ b/shell/browser/api/electron_api_url_loader.cc @@ -378,7 +378,7 @@ gin::Handle SimpleURLLoaderWrapper::Create( opts.Get("referrer", &request->referrer); bool credentials_specified = opts.Get("credentials", &request->credentials_mode); - std::map extra_headers; + std::vector> extra_headers; if (opts.Get("extraHeaders", &extra_headers)) { for (const auto& it : extra_headers) { if (!net::HttpUtil::IsValidHeaderName(it.first) || diff --git a/shell/common/gin_converters/net_converter.h b/shell/common/gin_converters/net_converter.h index 0d05fe5f5537..a90e3dd90ecb 100644 --- a/shell/common/gin_converters/net_converter.h +++ b/shell/common/gin_converters/net_converter.h @@ -6,6 +6,8 @@ #define SHELL_COMMON_GIN_CONVERTERS_NET_CONVERTER_H_ #include +#include +#include #include "gin/converter.h" #include "services/network/public/mojom/fetch_api.mojom.h" @@ -112,6 +114,35 @@ struct Converter { const net::RedirectInfo& val); }; +template +struct Converter>> { + static bool FromV8(v8::Isolate* isolate, + v8::Local value, + std::vector>* out) { + if (!value->IsObject()) + return false; + out->clear(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local obj = value.As(); + v8::Local keys = obj->GetPropertyNames(context).ToLocalChecked(); + for (uint32_t i = 0; i < keys->Length(); ++i) { + v8::Local v8key; + if (!keys->Get(context, i).ToLocal(&v8key)) + return false; + v8::Local v8value; + if (!obj->Get(context, v8key).ToLocal(&v8value)) + return false; + K key; + V value; + if (!ConvertFromV8(isolate, v8key, &key) || + !ConvertFromV8(isolate, v8value, &value)) + return false; + (*out).emplace_back(std::move(key), std::move(value)); + } + return true; + } +}; + } // namespace gin #endif // SHELL_COMMON_GIN_CONVERTERS_NET_CONVERTER_H_ diff --git a/spec-main/api-net-spec.ts b/spec-main/api-net-spec.ts index 4b2e2a4e93fb..4d229d664765 100644 --- a/spec-main/api-net-spec.ts +++ b/spec-main/api-net-spec.ts @@ -537,6 +537,27 @@ describe('net module', () => { await collectStreamBody(response); }); + it('should keep the order of headers', async () => { + const customHeaderNameA = 'X-Header-100'; + const customHeaderNameB = 'X-Header-200'; + const serverUrl = await respondOnce.toSingleURL((request, response) => { + const headerNames = Array.from(Object.keys(request.headers)); + const headerAIndex = headerNames.indexOf(customHeaderNameA.toLowerCase()); + const headerBIndex = headerNames.indexOf(customHeaderNameB.toLowerCase()); + expect(headerBIndex).to.be.below(headerAIndex); + response.statusCode = 200; + response.statusMessage = 'OK'; + response.end(); + }); + + const urlRequest = net.request(serverUrl); + urlRequest.setHeader(customHeaderNameB, 'b'); + urlRequest.setHeader(customHeaderNameA, 'a'); + const response = await getResponse(urlRequest); + expect(response.statusCode).to.equal(200); + await collectStreamBody(response); + }); + it('should be able to set cookie header line', async () => { const cookieHeaderName = 'Cookie'; const cookieHeaderValue = 'test=12345';