mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Fix HTTP spec issues by upgrading uWS version (#14853)
This commit is contained in:
@@ -16,8 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
// clang-format off
|
||||
#ifndef UWS_APP_H
|
||||
#define UWS_APP_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <charconv>
|
||||
@@ -619,4 +618,3 @@ typedef TemplatedApp<true> SSLApp;
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_APP_H
|
||||
@@ -16,8 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UWS_HTTPCONTEXT_H
|
||||
#define UWS_HTTPCONTEXT_H
|
||||
#pragma once
|
||||
|
||||
/* This class defines the main behavior of HTTP and emits various events */
|
||||
|
||||
@@ -27,6 +26,8 @@
|
||||
#include "AsyncSocket.h"
|
||||
#include "WebSocketData.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
#include "MoveOnlyFunction.h"
|
||||
@@ -171,7 +172,7 @@ private:
|
||||
#endif
|
||||
|
||||
/* The return value is entirely up to us to interpret. The HttpParser only care for whether the returned value is DIFFERENT or not from passed user */
|
||||
void *returnedSocket = httpResponseData->consumePostPadded(data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {
|
||||
auto [err, returnedSocket] = httpResponseData->consumePostPadded(data, (unsigned int) length, s, proxyParser, [httpContextData](void *s, HttpRequest *httpRequest) -> void * {
|
||||
/* For every request we reset the timeout and hang until user makes action */
|
||||
/* Warning: if we are in shutdown state, resetting the timer is a security issue! */
|
||||
us_socket_timeout(SSL, (us_socket_t *) s, 0);
|
||||
@@ -180,7 +181,9 @@ private:
|
||||
HttpResponseData<SSL> *httpResponseData = (HttpResponseData<SSL> *) us_socket_ext(SSL, (us_socket_t *) s);
|
||||
httpResponseData->offset = 0;
|
||||
|
||||
/* Are we not ready for another request yet? Terminate the connection. */
|
||||
/* Are we not ready for another request yet? Terminate the connection.
|
||||
* Important for denying async pipelining until, if ever, we want to suppot it.
|
||||
* Otherwise requests can get mixed up on the same connection. We still support sync pipelining. */
|
||||
if (httpResponseData->state & HttpResponseData<SSL>::HTTP_RESPONSE_PENDING) {
|
||||
us_socket_close(SSL, (us_socket_t *) s, 0, nullptr);
|
||||
return nullptr;
|
||||
@@ -280,10 +283,6 @@ private:
|
||||
}
|
||||
}
|
||||
return user;
|
||||
}, [](void *user) {
|
||||
/* Close any socket on HTTP errors */
|
||||
us_socket_close(SSL, (us_socket_t *) user, 0, nullptr);
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
/* Mark that we are no longer parsing Http */
|
||||
@@ -291,6 +290,9 @@ private:
|
||||
|
||||
/* If we got fullptr that means the parser wants us to close the socket from error (same as calling the errorHandler) */
|
||||
if (returnedSocket == FULLPTR) {
|
||||
/* For errors, we only deliver them "at most once". We don't care if they get halfways delivered or not. */
|
||||
us_socket_write(SSL, s, httpErrorResponses[err].data(), (int) httpErrorResponses[err].length(), false);
|
||||
us_socket_shutdown(SSL, s);
|
||||
/* Close any socket on HTTP errors */
|
||||
us_socket_close(SSL, s, 0, nullptr);
|
||||
/* This just makes the following code act as if the socket was closed from error inside the parser. */
|
||||
@@ -299,9 +301,8 @@ private:
|
||||
|
||||
/* We need to uncork in all cases, except for nullptr (closed socket, or upgraded socket) */
|
||||
if (returnedSocket != nullptr) {
|
||||
us_socket_t* returnedSocketPtr = (us_socket_t*) returnedSocket;
|
||||
/* We don't want open sockets to keep the event loop alive between HTTP requests */
|
||||
us_socket_unref(returnedSocketPtr);
|
||||
us_socket_unref((us_socket_t *) returnedSocket);
|
||||
|
||||
/* Timeout on uncork failure */
|
||||
auto [written, failed] = ((AsyncSocket<SSL> *) returnedSocket)->uncork();
|
||||
@@ -321,7 +322,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnedSocketPtr;
|
||||
return (us_socket_t *) returnedSocket;
|
||||
}
|
||||
|
||||
/* If we upgraded, check here (differ between nullptr close and nullptr upgrade) */
|
||||
@@ -483,10 +484,27 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
httpContextData->currentRouter->add(methods, pattern, [handler = std::move(handler)](auto *r) mutable {
|
||||
/* Record this route's parameter offsets */
|
||||
std::map<std::string, unsigned short, std::less<>> parameterOffsets;
|
||||
unsigned short offset = 0;
|
||||
for (unsigned int i = 0; i < pattern.length(); i++) {
|
||||
if (pattern[i] == ':') {
|
||||
i++;
|
||||
unsigned int start = i;
|
||||
while (i < pattern.length() && pattern[i] != '/') {
|
||||
i++;
|
||||
}
|
||||
parameterOffsets[std::string(pattern.data() + start, i - start)] = offset;
|
||||
//std::cout << "<" << std::string(pattern.data() + start, i - start) << "> is offset " << offset;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
httpContextData->currentRouter->add(methods, pattern, [handler = std::move(handler), parameterOffsets = std::move(parameterOffsets)](auto *r) mutable {
|
||||
auto user = r->getUserData();
|
||||
user.httpRequest->setYield(false);
|
||||
user.httpRequest->setParameters(r->getParameters());
|
||||
user.httpRequest->setParameterOffsets(¶meterOffsets);
|
||||
|
||||
/* Middleware? Automatically respond to expectations */
|
||||
std::string_view expect = user.httpRequest->getHeader("expect");
|
||||
@@ -528,4 +546,4 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_HTTPCONTEXT_H
|
||||
|
||||
|
||||
53
packages/bun-uws/src/HttpError.h
Normal file
53
packages/bun-uws/src/HttpError.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Authored by Alex Hultman, 2018-2023.
|
||||
* Intellectual property of third-party.
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UWS_HTTP_ERRORS
|
||||
#define UWS_HTTP_ERRORS
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace uWS {
|
||||
/* Possible errors from http parsing */
|
||||
enum HttpError {
|
||||
HTTP_ERROR_505_HTTP_VERSION_NOT_SUPPORTED = 1,
|
||||
HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 2,
|
||||
HTTP_ERROR_400_BAD_REQUEST = 3
|
||||
};
|
||||
|
||||
#ifndef UWS_HTTPRESPONSE_NO_WRITEMARK
|
||||
|
||||
/* Returned parser errors match this LUT. */
|
||||
static const std::string_view httpErrorResponses[] = {
|
||||
"", /* Zeroth place is no error so don't use it */
|
||||
"HTTP/1.1 505 HTTP Version Not Supported\r\nConnection: close\r\n\r\n<h1>HTTP Version Not Supported</h1><p>This server does not support HTTP/1.0.</p><hr><i>uWebSockets/20 Server</i>",
|
||||
"HTTP/1.1 431 Request Header Fields Too Large\r\nConnection: close\r\n\r\n<h1>Request Header Fields Too Large</h1><hr><i>uWebSockets/20 Server</i>",
|
||||
"HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n<h1>Bad Request</h1><hr><i>uWebSockets/20 Server</i>",
|
||||
};
|
||||
|
||||
#else
|
||||
/* Anonymized pages */
|
||||
static const std::string_view httpErrorResponses[] = {
|
||||
"", /* Zeroth place is no error so don't use it */
|
||||
"HTTP/1.1 505 HTTP Version Not Supported\r\nConnection: close\r\n\r\n",
|
||||
"HTTP/1.1 431 Request Header Fields Too Large\r\nConnection: close\r\n\r\n",
|
||||
"HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n"
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
42
packages/bun-uws/src/HttpErrors.h
Normal file
42
packages/bun-uws/src/HttpErrors.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Authored by Alex Hultman, 2018-2023.
|
||||
* Intellectual property of third-party.
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace uWS {
|
||||
/* Possible errors from http parsing */
|
||||
enum HttpError {
|
||||
HTTP_ERROR_505_HTTP_VERSION_NOT_SUPPORTED = 1,
|
||||
HTTP_ERROR_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 2,
|
||||
HTTP_ERROR_400_BAD_REQUEST = 3
|
||||
};
|
||||
|
||||
|
||||
/* Anonymized pages */
|
||||
static const std::string_view httpErrorResponses[] = {
|
||||
"", /* Zeroth place is no error so don't use it */
|
||||
"HTTP/1.1 505 HTTP Version Not Supported\r\nConnection: close\r\n\r\n",
|
||||
"HTTP/1.1 431 Request Header Fields Too Large\r\nConnection: close\r\n\r\n",
|
||||
"HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n"
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
// clang-format off
|
||||
#ifndef UWS_HTTPRESPONSEDATA_H
|
||||
#define UWS_HTTPRESPONSEDATA_H
|
||||
#pragma once
|
||||
|
||||
/* This data belongs to the HttpResponse */
|
||||
|
||||
@@ -106,4 +105,4 @@ struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_HTTPRESPONSEDATA_H
|
||||
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UWS_TOPICTREE_H
|
||||
#define UWS_TOPICTREE_H
|
||||
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
@@ -366,4 +364,4 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user