|
| 1 | +import { HttpRequest, HttpResponse } from "@smithy/protocol-http/src"; |
| 2 | +import { Readable } from "node:stream"; |
| 3 | +import { describe, expect, test as it, vi } from "vitest"; |
| 4 | + |
| 5 | +import { addHttpDebugLogMiddleware } from "./httpDebugLogging"; |
| 6 | + |
| 7 | +describe(addHttpDebugLogMiddleware.name, () => { |
| 8 | + describe("JSON", () => { |
| 9 | + const httpRequest = new HttpRequest({ |
| 10 | + headers: { |
| 11 | + header1: "headerValue1", |
| 12 | + }, |
| 13 | + query: { |
| 14 | + query1: "queryValue1", |
| 15 | + }, |
| 16 | + protocol: "https:", |
| 17 | + hostname: "localhost", |
| 18 | + path: "/path", |
| 19 | + body: JSON.stringify({ requestBody: "OK" }), |
| 20 | + }); |
| 21 | + |
| 22 | + const httpResponse = new HttpResponse({ |
| 23 | + headers: { |
| 24 | + responseHeader1: "responseHeaderValue1", |
| 25 | + }, |
| 26 | + statusCode: 200, |
| 27 | + body: Readable.from('{ "responseBody": "OK" }'), |
| 28 | + }); |
| 29 | + |
| 30 | + it("should pass http request and response data through a logger", async () => { |
| 31 | + const next = () => ({ |
| 32 | + response: httpResponse, |
| 33 | + }); |
| 34 | + const args = { |
| 35 | + request: httpRequest, |
| 36 | + }; |
| 37 | + |
| 38 | + const mwStack = { |
| 39 | + addRelativeTo(middleware: (next: Function, context: any) => (args) => Promise<any>): void { |
| 40 | + middleware(next, {})(args); |
| 41 | + }, |
| 42 | + } as any; |
| 43 | + |
| 44 | + const logger = { |
| 45 | + error: vi.fn(), |
| 46 | + warn: vi.fn(), |
| 47 | + info: vi.fn(), |
| 48 | + debug: vi.fn(), |
| 49 | + }; |
| 50 | + |
| 51 | + addHttpDebugLogMiddleware(mwStack, { |
| 52 | + request: { |
| 53 | + client: true, |
| 54 | + command: true, |
| 55 | + method: true, |
| 56 | + url: true, |
| 57 | + headers: true, |
| 58 | + formatBody: true, |
| 59 | + body: true, |
| 60 | + }, |
| 61 | + response: { |
| 62 | + statusCode: true, |
| 63 | + headers: true, |
| 64 | + body: true, |
| 65 | + formatBody: true, |
| 66 | + }, |
| 67 | + logger: logger, |
| 68 | + }); |
| 69 | + |
| 70 | + // inner tested fn is un-awaitable. |
| 71 | + await new Promise((r) => setTimeout(r, 100)); |
| 72 | + |
| 73 | + expect(vi.mocked(logger.debug).mock.calls.flat()).toEqual([ |
| 74 | + "200 GET UnknownClient UnknownCommand", |
| 75 | + " https://localhost/path", |
| 76 | + ` >> Request URL queryParams: { |
| 77 | + "query1": "queryValue1" |
| 78 | + }`, |
| 79 | + ` >>== Request Headers: { |
| 80 | + "header1": "headerValue1" |
| 81 | + }`, |
| 82 | + " >>>=== Request Body Start ======", |
| 83 | + ` { |
| 84 | + "requestBody": "OK" |
| 85 | + }`, |
| 86 | + " >>>=== Request Body End ======", |
| 87 | + ` <<== Response Headers: { |
| 88 | + "responseHeader1": "responseHeaderValue1" |
| 89 | + }`, |
| 90 | + " <<<=== Response Body Start ======", |
| 91 | + ` { |
| 92 | + "responseBody": "OK" |
| 93 | + }`, |
| 94 | + " <<<=== Response Body End ======", |
| 95 | + ]); |
| 96 | + }); |
| 97 | + }); |
| 98 | + |
| 99 | + describe("XML", () => { |
| 100 | + const httpRequest = new HttpRequest({ |
| 101 | + headers: { |
| 102 | + header1: "headerValue1", |
| 103 | + }, |
| 104 | + query: { |
| 105 | + query1: "queryValue1", |
| 106 | + }, |
| 107 | + protocol: "https:", |
| 108 | + hostname: "localhost", |
| 109 | + path: "/path", |
| 110 | + body: `<?xml version="1.0" encoding="UTF-8"?><WebsiteConfiguration xmlns="https://prod.company.com/doc/2006-03-01/"><ErrorDocument><Key>string</Key></ErrorDocument><IndexDocument><Suffix>string</Suffix></IndexDocument><RedirectAllRequestsTo><HostName>string</HostName><Protocol>string</Protocol></RedirectAllRequestsTo><RoutingRules><RoutingRule><Condition><HttpErrorCodeReturnedEquals>string</HttpErrorCodeReturnedEquals><KeyPrefixEquals>string</KeyPrefixEquals></Condition><Redirect><HostName>string</HostName><HttpRedirectCode>string</HttpRedirectCode><Protocol>string</Protocol><ReplaceKeyPrefixWith>string</ReplaceKeyPrefixWith><ReplaceKeyWith>string</ReplaceKeyWith></Redirect></RoutingRule></RoutingRules></WebsiteConfiguration>`, |
| 111 | + }); |
| 112 | + |
| 113 | + const httpResponse = new HttpResponse({ |
| 114 | + headers: { |
| 115 | + responseHeader1: "responseHeaderValue1", |
| 116 | + }, |
| 117 | + statusCode: 200, |
| 118 | + body: Readable.from( |
| 119 | + `<?xml version="1.0" encoding="UTF-8"?><BucketLoggingStatus><LoggingEnabled><TargetBucket>string</TargetBucket><TargetGrants><Grant><Grantee><DisplayName>string</DisplayName><EmailAddress>string</EmailAddress><ID>string</ID><xsi:type>string</xsi:type><URI>string</URI></Grantee><Permission>string</Permission></Grant></TargetGrants><TargetObjectKeyFormat><PartitionedPrefix><PartitionDateSource>string</PartitionDateSource></PartitionedPrefix><SimplePrefix></SimplePrefix></TargetObjectKeyFormat><TargetPrefix>string</TargetPrefix></LoggingEnabled></BucketLoggingStatus>` |
| 120 | + ), |
| 121 | + }); |
| 122 | + |
| 123 | + it("should pass http request and response data through a logger", async () => { |
| 124 | + const next = () => ({ |
| 125 | + response: httpResponse, |
| 126 | + }); |
| 127 | + const args = { |
| 128 | + request: httpRequest, |
| 129 | + }; |
| 130 | + |
| 131 | + const mwStack = { |
| 132 | + addRelativeTo(middleware: (next: Function, context: any) => (args) => Promise<any>): void { |
| 133 | + middleware(next, {})(args); |
| 134 | + }, |
| 135 | + } as any; |
| 136 | + |
| 137 | + addHttpDebugLogMiddleware(mwStack, "lines headers formatted"); |
| 138 | + const spy = vi.spyOn(console, "debug").mockImplementation(() => {}); |
| 139 | + |
| 140 | + // inner tested fn is un-awaitable. |
| 141 | + await new Promise((r) => setTimeout(r, 100)); |
| 142 | + |
| 143 | + expect(vi.mocked(spy).mock.calls.flat()).toEqual([ |
| 144 | + "200 GET UnknownClient UnknownCommand", |
| 145 | + " https://localhost/path", |
| 146 | + ` >> Request URL queryParams: { |
| 147 | + "query1": "queryValue1" |
| 148 | + }`, |
| 149 | + ` >>== Request Headers: { |
| 150 | + "header1": "headerValue1" |
| 151 | + }`, |
| 152 | + " >>>=== Request Body Start ======", |
| 153 | + ` <?xml version="1.0" encoding="UTF-8"?> |
| 154 | + <WebsiteConfiguration xmlns="https://prod.company.com/doc/2006-03-01/"> |
| 155 | + <ErrorDocument> |
| 156 | + <Key> |
| 157 | + string |
| 158 | + </Key> |
| 159 | + </ErrorDocument> |
| 160 | + <IndexDocument> |
| 161 | + <Suffix> |
| 162 | + string |
| 163 | + </Suffix> |
| 164 | + </IndexDocument> |
| 165 | + <RedirectAllRequestsTo> |
| 166 | + <HostName> |
| 167 | + string |
| 168 | + </HostName> |
| 169 | + <Protocol> |
| 170 | + string |
| 171 | + </Protocol> |
| 172 | + </RedirectAllRequestsTo> |
| 173 | + <RoutingRules> |
| 174 | + <RoutingRule> |
| 175 | + <Condition> |
| 176 | + <HttpErrorCodeReturnedEquals> |
| 177 | + string |
| 178 | + </HttpErrorCodeReturnedEquals> |
| 179 | + <KeyPrefixEquals> |
| 180 | + string |
| 181 | + </KeyPrefixEquals> |
| 182 | + </Condition> |
| 183 | + <Redirect> |
| 184 | + <HostName> |
| 185 | + string |
| 186 | + </HostName> |
| 187 | + <HttpRedirectCode> |
| 188 | + string |
| 189 | + </HttpRedirectCode> |
| 190 | + <Protocol> |
| 191 | + string |
| 192 | + </Protocol> |
| 193 | + <ReplaceKeyPrefixWith> |
| 194 | + string |
| 195 | + </ReplaceKeyPrefixWith> |
| 196 | + <ReplaceKeyWith> |
| 197 | + string |
| 198 | + </ReplaceKeyWith> |
| 199 | + </Redirect> |
| 200 | + </RoutingRule> |
| 201 | + </RoutingRules> |
| 202 | + </WebsiteConfiguration>`, |
| 203 | + " >>>=== Request Body End ======", |
| 204 | + ` <<== Response Headers: { |
| 205 | + "responseHeader1": "responseHeaderValue1" |
| 206 | + }`, |
| 207 | + " <<<=== Response Body Start ======", |
| 208 | + ` <?xml version="1.0" encoding="UTF-8"?> |
| 209 | + <BucketLoggingStatus> |
| 210 | + <LoggingEnabled> |
| 211 | + <TargetBucket> |
| 212 | + string |
| 213 | + </TargetBucket> |
| 214 | + <TargetGrants> |
| 215 | + <Grant> |
| 216 | + <Grantee> |
| 217 | + <DisplayName> |
| 218 | + string |
| 219 | + </DisplayName> |
| 220 | + <EmailAddress> |
| 221 | + string |
| 222 | + </EmailAddress> |
| 223 | + <ID> |
| 224 | + string |
| 225 | + </ID> |
| 226 | + <xsi:type> |
| 227 | + string |
| 228 | + </xsi:type> |
| 229 | + <URI> |
| 230 | + string |
| 231 | + </URI> |
| 232 | + </Grantee> |
| 233 | + <Permission> |
| 234 | + string |
| 235 | + </Permission> |
| 236 | + </Grant> |
| 237 | + </TargetGrants> |
| 238 | + <TargetObjectKeyFormat> |
| 239 | + <PartitionedPrefix> |
| 240 | + <PartitionDateSource> |
| 241 | + string |
| 242 | + </PartitionDateSource> |
| 243 | + </PartitionedPrefix> |
| 244 | + <SimplePrefix> |
| 245 | + </SimplePrefix> |
| 246 | + </TargetObjectKeyFormat> |
| 247 | + <TargetPrefix> |
| 248 | + string |
| 249 | + </TargetPrefix> |
| 250 | + </LoggingEnabled> |
| 251 | + </BucketLoggingStatus>`, |
| 252 | + " <<<=== Response Body End ======", |
| 253 | + ]); |
| 254 | + }); |
| 255 | + }); |
| 256 | +}); |
0 commit comments