/* * Copyright (c) 2022 Huawei Device Co., Ltd. * 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. */ #include "common/log_wrapper.h" #include "http.h" namespace OHOS::ArkCompiler::Toolchain { /* static */ std::string HttpBase::DecodeHeader(const std::string& headersText, std::string_view headerName) { auto startPos = headersText.find(headerName); if (startPos != std::string::npos) { auto endOfLinePos = headersText.find(EOL, startPos); startPos += headerName.size(); if (startPos < headersText.size() && startPos < endOfLinePos) { return headersText.substr(startPos, endOfLinePos - startPos); } } return ""; } /* static */ std::string HttpRequest::DecodeVersion(const std::string& request, std::string::size_type methodStartPos) { if (methodStartPos >= request.size()) { return ""; } auto endOfLinePos = request.find(EOL, methodStartPos); // the typical header is "GET /chat HTTP/1.1", where protocol version is located after the second space symbol methodStartPos = request.find(' ', methodStartPos); if (methodStartPos != std::string::npos) { methodStartPos = request.find(' ', methodStartPos + 1); } if (methodStartPos != std::string::npos && methodStartPos + 1 < request.size() && methodStartPos + 1 < endOfLinePos) { return request.substr(methodStartPos + 1, endOfLinePos - (methodStartPos + 1)); } return ""; } // request example can be found at https://www.rfc-editor.org/rfc/rfc6455#section-1.3 /* static */ bool HttpRequest::Decode(const std::string& request, HttpRequest& parsed) { auto pos = request.find(GET); if (pos == std::string::npos) { LOGW("Handshake failed: lack of necessary info"); return false; } parsed.version = DecodeVersion(request, pos); parsed.connection = DecodeHeader(request, CONNECTION); parsed.upgrade = DecodeHeader(request, UPGRADE); parsed.secWebSocketKey = DecodeHeader(request, SEC_WEBSOCKET_KEY); return true; } /* static */ std::string HttpResponse::DecodeVersion(const std::string& response, std::string::size_type versionStartPos) { // status-line example: "HTTP/1.1 404 Not Found" if (versionStartPos < response.size()) { auto versionEndPos = response.find(' ', versionStartPos); if (versionEndPos != std::string::npos) { return response.substr(versionStartPos, versionEndPos - versionStartPos); } } return ""; } /* static */ std::string HttpResponse::DecodeStatus(const std::string& response, std::string::size_type versionEndPos) { // status-line example: "HTTP/1.1 404 Not Found" if (versionEndPos < response.size() && response[versionEndPos] == ' ') { auto statusStartPos = response.find_first_not_of(' ', versionEndPos); if (statusStartPos != std::string::npos) { auto statusEndPos = response.find(' ', statusStartPos); statusEndPos = (statusEndPos == std::string::npos) ? response.find(EOL, statusStartPos) : statusEndPos; if (statusEndPos != std::string::npos) { return response.substr(statusStartPos, statusEndPos - statusStartPos); } } } return ""; } // request example can be found at https://www.rfc-editor.org/rfc/rfc6455#section-1.2 /* static */ bool HttpResponse::Decode(const std::string& response, HttpResponse& parsed) { // find start of status-line auto versionStartPos = response.find("HTTP"); if (versionStartPos == std::string::npos) { LOGW("Handshake failed: lack of necessary info, no status-line found"); return false; } parsed.version = DecodeVersion(response, versionStartPos); parsed.status = DecodeStatus(response, versionStartPos + parsed.version.size()); parsed.connection = DecodeHeader(response, CONNECTION); parsed.upgrade = DecodeHeader(response, UPGRADE); parsed.secWebSocketAccept = DecodeHeader(response, SEC_WEBSOCKET_ACCEPT); return true; } } // namespace OHOS::ArkCompiler::Toolchain