1/* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2013 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25#include "shrpx_downstream_test.h" 26 27#include <iostream> 28 29#include <CUnit/CUnit.h> 30 31#include "shrpx_downstream.h" 32 33namespace shrpx { 34 35void test_downstream_field_store_append_last_header(void) { 36 BlockAllocator balloc(16, 16); 37 FieldStore fs(balloc, 0); 38 fs.alloc_add_header_name(StringRef::from_lit("alpha")); 39 auto bravo = StringRef::from_lit("BRAVO"); 40 fs.append_last_header_key(bravo.c_str(), bravo.size()); 41 // Add more characters so that relloc occurs 42 auto golf = StringRef::from_lit("golF0123456789"); 43 fs.append_last_header_key(golf.c_str(), golf.size()); 44 45 auto charlie = StringRef::from_lit("Charlie"); 46 fs.append_last_header_value(charlie.c_str(), charlie.size()); 47 auto delta = StringRef::from_lit("deltA"); 48 fs.append_last_header_value(delta.c_str(), delta.size()); 49 // Add more characters so that relloc occurs 50 auto echo = StringRef::from_lit("echo0123456789"); 51 fs.append_last_header_value(echo.c_str(), echo.size()); 52 53 fs.add_header_token(StringRef::from_lit("echo"), 54 StringRef::from_lit("foxtrot"), false, -1); 55 56 auto ans = 57 HeaderRefs{{StringRef::from_lit("alphabravogolf0123456789"), 58 StringRef::from_lit("CharliedeltAecho0123456789")}, 59 {StringRef::from_lit("echo"), StringRef::from_lit("foxtrot")}}; 60 CU_ASSERT(ans == fs.headers()); 61} 62 63void test_downstream_field_store_header(void) { 64 BlockAllocator balloc(16, 16); 65 FieldStore fs(balloc, 0); 66 fs.add_header_token(StringRef::from_lit("alpha"), StringRef::from_lit("0"), 67 false, -1); 68 fs.add_header_token(StringRef::from_lit(":authority"), 69 StringRef::from_lit("1"), false, http2::HD__AUTHORITY); 70 fs.add_header_token(StringRef::from_lit("content-length"), 71 StringRef::from_lit("2"), false, 72 http2::HD_CONTENT_LENGTH); 73 74 // By token 75 CU_ASSERT(HeaderRef(StringRef{":authority"}, StringRef{"1"}) == 76 *fs.header(http2::HD__AUTHORITY)); 77 CU_ASSERT(nullptr == fs.header(http2::HD__METHOD)); 78 79 // By name 80 CU_ASSERT(HeaderRef(StringRef{"alpha"}, StringRef{"0"}) == 81 *fs.header(StringRef::from_lit("alpha"))); 82 CU_ASSERT(nullptr == fs.header(StringRef::from_lit("bravo"))); 83} 84 85void test_downstream_crumble_request_cookie(void) { 86 Downstream d(nullptr, nullptr, 0); 87 auto &req = d.request(); 88 req.fs.add_header_token(StringRef::from_lit(":method"), 89 StringRef::from_lit("get"), false, -1); 90 req.fs.add_header_token(StringRef::from_lit(":path"), 91 StringRef::from_lit("/"), false, -1); 92 req.fs.add_header_token(StringRef::from_lit("cookie"), 93 StringRef::from_lit("alpha; bravo; ; ;; charlie;;"), 94 true, http2::HD_COOKIE); 95 req.fs.add_header_token(StringRef::from_lit("cookie"), 96 StringRef::from_lit(";delta"), false, 97 http2::HD_COOKIE); 98 req.fs.add_header_token(StringRef::from_lit("cookie"), 99 StringRef::from_lit("echo"), false, http2::HD_COOKIE); 100 101 std::vector<nghttp2_nv> nva; 102 d.crumble_request_cookie(nva); 103 104 auto num_cookies = d.count_crumble_request_cookie(); 105 106 CU_ASSERT(5 == nva.size()); 107 CU_ASSERT(5 == num_cookies); 108 109 HeaderRefs cookies; 110 std::transform(std::begin(nva), std::end(nva), std::back_inserter(cookies), 111 [](const nghttp2_nv &nv) { 112 return HeaderRef(StringRef{nv.name, nv.namelen}, 113 StringRef{nv.value, nv.valuelen}, 114 nv.flags & NGHTTP2_NV_FLAG_NO_INDEX); 115 }); 116 117 HeaderRefs ans = { 118 {StringRef::from_lit("cookie"), StringRef::from_lit("alpha")}, 119 {StringRef::from_lit("cookie"), StringRef::from_lit("bravo")}, 120 {StringRef::from_lit("cookie"), StringRef::from_lit("charlie")}, 121 {StringRef::from_lit("cookie"), StringRef::from_lit("delta")}, 122 {StringRef::from_lit("cookie"), StringRef::from_lit("echo")}}; 123 124 CU_ASSERT(ans == cookies); 125 CU_ASSERT(cookies[0].no_index); 126 CU_ASSERT(cookies[1].no_index); 127 CU_ASSERT(cookies[2].no_index); 128} 129 130void test_downstream_assemble_request_cookie(void) { 131 Downstream d(nullptr, nullptr, 0); 132 auto &req = d.request(); 133 134 req.fs.add_header_token(StringRef::from_lit(":method"), 135 StringRef::from_lit("get"), false, -1); 136 req.fs.add_header_token(StringRef::from_lit(":path"), 137 StringRef::from_lit("/"), false, -1); 138 req.fs.add_header_token(StringRef::from_lit("cookie"), 139 StringRef::from_lit("alpha"), false, 140 http2::HD_COOKIE); 141 req.fs.add_header_token(StringRef::from_lit("cookie"), 142 StringRef::from_lit("bravo;"), false, 143 http2::HD_COOKIE); 144 req.fs.add_header_token(StringRef::from_lit("cookie"), 145 StringRef::from_lit("charlie; "), false, 146 http2::HD_COOKIE); 147 req.fs.add_header_token(StringRef::from_lit("cookie"), 148 StringRef::from_lit("delta;;"), false, 149 http2::HD_COOKIE); 150 CU_ASSERT("alpha; bravo; charlie; delta" == d.assemble_request_cookie()); 151} 152 153void test_downstream_rewrite_location_response_header(void) { 154 Downstream d(nullptr, nullptr, 0); 155 auto &req = d.request(); 156 auto &resp = d.response(); 157 d.set_request_downstream_host(StringRef::from_lit("localhost2")); 158 req.authority = StringRef::from_lit("localhost:8443"); 159 resp.fs.add_header_token(StringRef::from_lit("location"), 160 StringRef::from_lit("http://localhost2:3000/"), 161 false, http2::HD_LOCATION); 162 d.rewrite_location_response_header(StringRef::from_lit("https")); 163 auto location = resp.fs.header(http2::HD_LOCATION); 164 CU_ASSERT("https://localhost:8443/" == (*location).value); 165} 166 167void test_downstream_supports_non_final_response(void) { 168 Downstream d(nullptr, nullptr, 0); 169 auto &req = d.request(); 170 171 req.http_major = 3; 172 req.http_minor = 0; 173 174 CU_ASSERT(d.supports_non_final_response()); 175 176 req.http_major = 2; 177 req.http_minor = 0; 178 179 CU_ASSERT(d.supports_non_final_response()); 180 181 req.http_major = 1; 182 req.http_minor = 1; 183 184 CU_ASSERT(d.supports_non_final_response()); 185 186 req.http_major = 1; 187 req.http_minor = 0; 188 189 CU_ASSERT(!d.supports_non_final_response()); 190 191 req.http_major = 0; 192 req.http_minor = 9; 193 194 CU_ASSERT(!d.supports_non_final_response()); 195} 196 197void test_downstream_find_affinity_cookie(void) { 198 Downstream d(nullptr, nullptr, 0); 199 200 auto &req = d.request(); 201 req.fs.add_header_token(StringRef::from_lit("cookie"), StringRef{}, false, 202 http2::HD_COOKIE); 203 req.fs.add_header_token(StringRef::from_lit("cookie"), 204 StringRef::from_lit("a=b;;c=d"), false, 205 http2::HD_COOKIE); 206 req.fs.add_header_token(StringRef::from_lit("content-length"), 207 StringRef::from_lit("599"), false, 208 http2::HD_CONTENT_LENGTH); 209 req.fs.add_header_token(StringRef::from_lit("cookie"), 210 StringRef::from_lit("lb=deadbeef;LB=f1f2f3f4"), false, 211 http2::HD_COOKIE); 212 req.fs.add_header_token(StringRef::from_lit("cookie"), 213 StringRef::from_lit("short=e1e2e3e"), false, 214 http2::HD_COOKIE); 215 216 uint32_t aff; 217 218 aff = d.find_affinity_cookie(StringRef::from_lit("lb")); 219 220 CU_ASSERT(0xdeadbeef == aff); 221 222 aff = d.find_affinity_cookie(StringRef::from_lit("LB")); 223 224 CU_ASSERT(0xf1f2f3f4 == aff); 225 226 aff = d.find_affinity_cookie(StringRef::from_lit("short")); 227 228 CU_ASSERT(0 == aff); 229} 230 231} // namespace shrpx 232