1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "common/log_wrapper.h" 17#include "http.h" 18 19namespace OHOS::ArkCompiler::Toolchain { 20/* static */ 21std::string HttpBase::DecodeHeader(const std::string& headersText, std::string_view headerName) 22{ 23 auto startPos = headersText.find(headerName); 24 if (startPos != std::string::npos) { 25 auto endOfLinePos = headersText.find(EOL, startPos); 26 startPos += headerName.size(); 27 if (startPos < headersText.size() && startPos < endOfLinePos) { 28 return headersText.substr(startPos, endOfLinePos - startPos); 29 } 30 } 31 return ""; 32} 33 34/* static */ 35std::string HttpRequest::DecodeVersion(const std::string& request, std::string::size_type methodStartPos) 36{ 37 if (methodStartPos >= request.size()) { 38 return ""; 39 } 40 41 auto endOfLinePos = request.find(EOL, methodStartPos); 42 // the typical header is "GET /chat HTTP/1.1", where protocol version is located after the second space symbol 43 methodStartPos = request.find(' ', methodStartPos); 44 if (methodStartPos != std::string::npos) { 45 methodStartPos = request.find(' ', methodStartPos + 1); 46 } 47 if (methodStartPos != std::string::npos && 48 methodStartPos + 1 < request.size() && 49 methodStartPos + 1 < endOfLinePos) { 50 return request.substr(methodStartPos + 1, endOfLinePos - (methodStartPos + 1)); 51 } 52 return ""; 53} 54 55// request example can be found at https://www.rfc-editor.org/rfc/rfc6455#section-1.3 56/* static */ 57bool HttpRequest::Decode(const std::string& request, HttpRequest& parsed) 58{ 59 auto pos = request.find(GET); 60 if (pos == std::string::npos) { 61 LOGW("Handshake failed: lack of necessary info"); 62 return false; 63 } 64 65 parsed.version = DecodeVersion(request, pos); 66 parsed.connection = DecodeHeader(request, CONNECTION); 67 parsed.upgrade = DecodeHeader(request, UPGRADE); 68 parsed.secWebSocketKey = DecodeHeader(request, SEC_WEBSOCKET_KEY); 69 70 return true; 71} 72 73/* static */ 74std::string HttpResponse::DecodeVersion(const std::string& response, std::string::size_type versionStartPos) 75{ 76 // status-line example: "HTTP/1.1 404 Not Found" 77 if (versionStartPos < response.size()) { 78 auto versionEndPos = response.find(' ', versionStartPos); 79 if (versionEndPos != std::string::npos) { 80 return response.substr(versionStartPos, versionEndPos - versionStartPos); 81 } 82 } 83 return ""; 84} 85 86/* static */ 87std::string HttpResponse::DecodeStatus(const std::string& response, std::string::size_type versionEndPos) 88{ 89 // status-line example: "HTTP/1.1 404 Not Found" 90 if (versionEndPos < response.size() && response[versionEndPos] == ' ') { 91 auto statusStartPos = response.find_first_not_of(' ', versionEndPos); 92 if (statusStartPos != std::string::npos) { 93 auto statusEndPos = response.find(' ', statusStartPos); 94 statusEndPos = (statusEndPos == std::string::npos) ? response.find(EOL, statusStartPos) : statusEndPos; 95 if (statusEndPos != std::string::npos) { 96 return response.substr(statusStartPos, statusEndPos - statusStartPos); 97 } 98 } 99 } 100 return ""; 101} 102 103// request example can be found at https://www.rfc-editor.org/rfc/rfc6455#section-1.2 104/* static */ 105bool HttpResponse::Decode(const std::string& response, HttpResponse& parsed) 106{ 107 // find start of status-line 108 auto versionStartPos = response.find("HTTP"); 109 if (versionStartPos == std::string::npos) { 110 LOGW("Handshake failed: lack of necessary info, no status-line found"); 111 return false; 112 } 113 114 parsed.version = DecodeVersion(response, versionStartPos); 115 parsed.status = DecodeStatus(response, versionStartPos + parsed.version.size()); 116 parsed.connection = DecodeHeader(response, CONNECTION); 117 parsed.upgrade = DecodeHeader(response, UPGRADE); 118 parsed.secWebSocketAccept = DecodeHeader(response, SEC_WEBSOCKET_ACCEPT); 119 120 return true; 121} 122} // namespace OHOS::ArkCompiler::Toolchain 123