diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java index 72883319..e7e448ab 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayCustomAuthorizerEvent.java @@ -1,5 +1,6 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -26,7 +27,7 @@ public class APIGatewayCustomAuthorizerEvent { private String resource; private String path; private String httpMethod; - private Map headers; + private HttpHeaders headers; private Map queryStringParameters; private Map pathParameters; private Map stageVariables; diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java index f9c118ca..9257de13 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyRequestEvent.java @@ -1,8 +1,9 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; + import java.io.Serializable; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Class that represents an APIGatewayProxyRequestEvent @@ -17,9 +18,9 @@ public class APIGatewayProxyRequestEvent implements Serializable, Cloneable { private String httpMethod; - private Map headers; + private HttpHeaders headers; - private Map> multiValueHeaders; + private HttpHeaders> multiValueHeaders; private Map queryStringParameters; @@ -67,7 +68,8 @@ public static class ProxyRequestContext implements Serializable, Cloneable { /** * default constructor */ - public ProxyRequestContext() {} + public ProxyRequestContext() { + } /** * @return account id that owns Lambda function @@ -101,7 +103,7 @@ public void setAuthorizer(final Map authorizer) { } /** - * @return API Gateway stage name + * @return API Gateway stage name */ public String getStage() { return stage; @@ -286,14 +288,14 @@ public ProxyRequestContext withPath(String path) { /** * @return The name of the operation being performed - * */ + */ public String getOperationName() { return operationName; } /** * @param operationName The name of the operation being performed - * */ + */ public void setOperationName(String operationName) { this.operationName = operationName; } @@ -307,7 +309,6 @@ public ProxyRequestContext withOperationName(String operationName) { * Returns a string representation of this object; useful for testing and debugging. * * @return A string representation of this object. - * * @see Object#toString() */ @Override @@ -412,7 +413,7 @@ public int hashCode() { hashCode = prime * hashCode + ((getApiId() == null) ? 0 : getApiId().hashCode()); hashCode = prime * hashCode + ((getPath() == null) ? 0 : getPath().hashCode()); hashCode = prime * hashCode + ((getAuthorizer() == null) ? 0 : getAuthorizer().hashCode()); - hashCode = prime * hashCode + ((getOperationName() == null) ? 0: getOperationName().hashCode()); + hashCode = prime * hashCode + ((getOperationName() == null) ? 0 : getOperationName().hashCode()); return hashCode; } @@ -457,7 +458,8 @@ public static class RequestIdentity implements Serializable, Cloneable { /** * default constructor */ - public RequestIdentity() {} + public RequestIdentity() { + } /** * @return The Cognito identity pool id. @@ -739,7 +741,6 @@ public RequestIdentity withAccessKey(String accessKey) { * Returns a string representation of this object; useful for testing and debugging. * * @return A string representation of this object. - * * @see Object#toString() */ @Override @@ -869,7 +870,8 @@ public RequestIdentity clone() { /** * default constructor */ - public APIGatewayProxyRequestEvent() {} + public APIGatewayProxyRequestEvent() { + } /** * @return The resource path defined in API Gateway @@ -951,7 +953,15 @@ public Map getHeaders() { * @param headers The headers sent with the request */ public void setHeaders(Map headers) { - this.headers = headers; + if (headers == null || headers.isEmpty()) { + this.headers = null; + return; + } + + if (this.headers == null) { + this.headers = new HttpHeaders<>(); + } + this.headers.putAll(headers); } /** @@ -974,7 +984,15 @@ public Map> getMultiValueHeaders() { * @param multiValueHeaders The multi value headers sent with the request */ public void setMultiValueHeaders(Map> multiValueHeaders) { - this.multiValueHeaders = multiValueHeaders; + if (multiValueHeaders == null || multiValueHeaders.isEmpty()) { + this.multiValueHeaders = null; + return; + } + + if (this.multiValueHeaders == null) { + this.multiValueHeaders = new HttpHeaders<>(); + } + this.multiValueHeaders.putAll(multiValueHeaders); } /** @@ -1167,7 +1185,6 @@ public APIGatewayProxyRequestEvent withIsBase64Encoded(Boolean isBase64Encoded) * Returns a string representation of this object; useful for testing and debugging. * * @return A string representation of this object. - * * @see Object#toString() */ @Override diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyResponseEvent.java index fb1f87c3..18c625cd 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyResponseEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayProxyResponseEvent.java @@ -1,5 +1,7 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; + import java.io.Serializable; import java.util.List; import java.util.Map; @@ -13,9 +15,9 @@ public class APIGatewayProxyResponseEvent implements Serializable, Cloneable { private Integer statusCode; - private Map headers; + private HttpHeaders headers; - private Map> multiValueHeaders; + private HttpHeaders> multiValueHeaders; private String body; @@ -60,7 +62,15 @@ public Map getHeaders() { * @param headers The Http headers return in the response */ public void setHeaders(Map headers) { - this.headers = headers; + if (headers == null || headers.isEmpty()) { + this.headers = null; + return; + } + + if (this.headers == null) { + this.headers = new HttpHeaders<>(); + } + this.headers.putAll(headers); } /** @@ -83,7 +93,15 @@ public Map> getMultiValueHeaders() { * @param multiValueHeaders the Http multi value headers to return in the response */ public void setMultiValueHeaders(Map> multiValueHeaders) { - this.multiValueHeaders = multiValueHeaders; + if (multiValueHeaders == null || multiValueHeaders.isEmpty()) { + this.multiValueHeaders = null; + return; + } + + if (this.multiValueHeaders == null) { + this.multiValueHeaders = new HttpHeaders<>(); + } + this.multiValueHeaders.putAll(multiValueHeaders); } /** diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java index 6abfe051..893cce24 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2CustomAuthorizerEvent.java @@ -1,5 +1,6 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -31,7 +32,7 @@ public class APIGatewayV2CustomAuthorizerEvent { private String rawPath; private String rawQueryString; private List cookies; - private Map headers; + private HttpHeaders headers; private Map queryStringParameters; private RequestContext requestContext; private Map pathParameters; diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java index 34894023..8dda8b54 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPEvent.java @@ -13,6 +13,7 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -34,7 +35,7 @@ public class APIGatewayV2HTTPEvent { private String rawPath; private String rawQueryString; private List cookies; - private Map headers; + private HttpHeaders headers; private Map queryStringParameters; private Map pathParameters; private Map stageVariables; @@ -42,6 +43,18 @@ public class APIGatewayV2HTTPEvent { private boolean isBase64Encoded; private RequestContext requestContext; + public void setHeaders(Map headers) { + if (headers == null || headers.isEmpty()) { + this.headers = null; + return; + } + + if (this.headers == null) { + this.headers = new HttpHeaders<>(); + } + this.headers.putAll(headers); + } + @AllArgsConstructor @Builder(setterPrefix = "with") @Data diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java index 2bd81fad..101dd4ea 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2HTTPResponse.java @@ -13,6 +13,7 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -27,9 +28,44 @@ @NoArgsConstructor public class APIGatewayV2HTTPResponse { private int statusCode; - private Map headers; - private Map> multiValueHeaders; + private HttpHeaders headers; + private HttpHeaders> multiValueHeaders; private List cookies; private String body; private boolean isBase64Encoded; + + public static APIGatewayV2HTTPResponseBuilder builder() { + return new APIGatewayV2HTTPResponseBuilder(); + } + + public static class APIGatewayV2HTTPResponseBuilder { + private HttpHeaders headers; + private HttpHeaders> multiValueHeaders; + + public APIGatewayV2HTTPResponseBuilder withHeaders(Map headers) { + if (headers == null || headers.isEmpty()) { + this.headers = null; + return this; + } + + if (this.headers == null) { + this.headers = new HttpHeaders<>(); + } + this.headers.putAll(headers); + return this; + } + + public APIGatewayV2HTTPResponseBuilder withMultiValueHeaders(Map> multiValueHeaders) { + if (multiValueHeaders == null || multiValueHeaders.isEmpty()) { + this.multiValueHeaders = null; + return this; + } + + if (this.multiValueHeaders == null) { + this.multiValueHeaders = new HttpHeaders<>(); + } + this.multiValueHeaders.putAll(multiValueHeaders); + return this; + } + } } diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java index 87e4284c..3682db5b 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/APIGatewayV2WebSocketResponse.java @@ -1,5 +1,7 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; + import java.io.Serializable; import java.util.Map; @@ -12,8 +14,8 @@ public class APIGatewayV2WebSocketResponse implements Serializable, Cloneable { private boolean isBase64Encoded = false; private int statusCode; - private Map headers; - private Map multiValueHeaders; + private HttpHeaders headers; + private HttpHeaders multiValueHeaders; private String body; public boolean isIsBase64Encoded() { @@ -37,7 +39,12 @@ public Map getHeaders() { } public void setHeaders(Map headers) { - this.headers = headers; + if (this.headers == null && headers != null && !headers.isEmpty()) { + this.headers = new HttpHeaders<>(); + } + if (headers != null && !headers.isEmpty()) { + this.headers.putAll(headers); + } } public Map getMultiValueHeaders() { @@ -45,7 +52,12 @@ public Map getMultiValueHeaders() { } public void setMultiValueHeaders(Map multiValueHeaders) { - this.multiValueHeaders = multiValueHeaders; + if (this.multiValueHeaders == null && multiValueHeaders != null && !multiValueHeaders.isEmpty()) { + this.multiValueHeaders = new HttpHeaders<>(); + } + if (multiValueHeaders != null && !multiValueHeaders.isEmpty()) { + this.multiValueHeaders.putAll(multiValueHeaders); + } } public String getBody() { diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java index e7b33117..f42be334 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerRequestEvent.java @@ -1,5 +1,6 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; import lombok.Data; import lombok.NoArgsConstructor; @@ -40,8 +41,8 @@ public static class RequestContext implements Serializable, Cloneable { private String path; private Map queryStringParameters; private Map> multiValueQueryStringParameters; - private Map headers; - private Map> multiValueHeaders; + private HttpHeaders headers; + private HttpHeaders> multiValueHeaders; private String body; private boolean isBase64Encoded; diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java index 135de143..3da8951e 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/ApplicationLoadBalancerResponseEvent.java @@ -1,5 +1,6 @@ package com.amazonaws.services.lambda.runtime.events; +import com.amazonaws.services.lambda.runtime.events.models.HttpHeaders; import lombok.Data; import lombok.NoArgsConstructor; @@ -22,8 +23,8 @@ public class ApplicationLoadBalancerResponseEvent implements Serializable, Clone private int statusCode; private String statusDescription; private boolean isBase64Encoded; - private Map headers; - private Map> multiValueHeaders; + private HttpHeaders headers; + private HttpHeaders> multiValueHeaders; private String body; } diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/HttpHeaders.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/HttpHeaders.java new file mode 100644 index 00000000..caa0e7a7 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/models/HttpHeaders.java @@ -0,0 +1,78 @@ +package com.amazonaws.services.lambda.runtime.events.models; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +/** + * Class that represents Http Headers. + *
+ * Not using a standard map, because we need insensitive case. + */ +public class HttpHeaders implements Map { + + // Headers are case insensitive (https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2) + private final Map map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return map.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return map.containsValue(value); + } + + @Override + public T get(Object key) { + return map.get(key); + } + + @Override + public T put(String key, T value) { + return map.put(key, value); + } + + @Override + public T remove(Object key) { + return map.remove(key); + } + + @Override + public void putAll(Map m) { + map.putAll(m); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public Set keySet() { + return map.keySet(); + } + + @Override + public Collection values() { + return map.values(); + } + + @Override + public Set> entrySet() { + return map.entrySet(); + } + +} diff --git a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java index aecd0c6a..de9f8974 100644 --- a/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java +++ b/aws-lambda-java-tests/src/test/java/com/amazonaws/services/lambda/runtime/tests/EventLoaderTest.java @@ -26,6 +26,11 @@ public void testLoadApiGatewayRestEvent() { assertThat(event).isNotNull(); assertThat(event.getBody()).isEqualTo("Hello from Lambda!"); + + assertThat(event.getHeaders().get("Header1")).isEqualTo("value1"); + assertThat(event.getHeaders().get("header1")).isEqualTo("value1"); + assertThat(event.getMultiValueHeaders().get("header1")).contains("value1", "value11"); + assertThat(event.getMultiValueHeaders().get("Header1")).contains("value1", "value11"); assertThat(event.getHeaders()).hasSize(2); } @@ -35,6 +40,9 @@ public void testLoadApiGatewayHttpEvent() { assertThat(event).isNotNull(); assertThat(event.getBody()).isEqualTo("Hello from Lambda!!"); + + assertThat(event.getHeaders().get("Header1")).isEqualTo("value1"); + assertThat(event.getHeaders().get("header1")).isEqualTo("value1"); } @Test @@ -44,6 +52,9 @@ public void testLoadAPIGatewayCustomAuthorizerEvent() { assertThat(event).isNotNull(); assertThat(event.getRequestContext().getHttpMethod()).isEqualTo("GET"); assertThat(event.getHeaders()).hasSize(8); + + assertThat(event.getHeaders().get("Accept")).isEqualTo("application/json"); + assertThat(event.getHeaders().get("accept")).isEqualTo("application/json"); } @Test @@ -53,6 +64,9 @@ public void testLoadAPIGatewayV2CustomAuthorizerEvent() { assertThat(event).isNotNull(); assertThat(event.getRequestContext().getHttp().getMethod()).isEqualTo("POST"); assertThat(event.getRequestContext().getTimeEpoch()).isEqualTo(Instant.ofEpochMilli(1583348638390L)); + + assertThat(event.getHeaders().get("Header1")).isEqualTo("Value1"); + assertThat(event.getHeaders().get("header1")).isEqualTo("Value1"); } @Test @@ -61,6 +75,9 @@ public void testLoadApplicationLoadBalancerRequestEvent() { assertThat(event).isNotNull(); assertThat(event.getBody()).isEqualTo("Hello from ELB"); + + assertThat(event.getHeaders().get("Accept")).isEqualTo("application/json"); + assertThat(event.getHeaders().get("accept")).isEqualTo("application/json"); } @Test diff --git a/aws-lambda-java-tests/src/test/resources/apigw_auth.json b/aws-lambda-java-tests/src/test/resources/apigw_auth.json index eb73956e..bfe2d112 100644 --- a/aws-lambda-java-tests/src/test/resources/apigw_auth.json +++ b/aws-lambda-java-tests/src/test/resources/apigw_auth.json @@ -10,6 +10,7 @@ "headers": { "X-AMZ-Date": "20170718T062915Z", "Accept": "*/*", + "accept": "application/json", "HeaderAuth1": "headerValue1", "CloudFront-Viewer-Country": "US", "CloudFront-Forwarded-Proto": "https", diff --git a/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json b/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json index a603763e..70024f22 100644 --- a/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json +++ b/aws-lambda-java-tests/src/test/resources/apigw_auth_v2.json @@ -8,8 +8,9 @@ "rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value", "cookies": [ "cookie1", "cookie2" ], "headers": { - "Header1": "value1", - "Header2": "value2" + "header1": "value1", + "Header2": "value2", + "Header1": "Value1" }, "queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" }, "requestContext": { diff --git a/aws-lambda-java-tests/src/test/resources/apigw_http_event.json b/aws-lambda-java-tests/src/test/resources/apigw_http_event.json index 88f4e5b4..43c7e4b3 100644 --- a/aws-lambda-java-tests/src/test/resources/apigw_http_event.json +++ b/aws-lambda-java-tests/src/test/resources/apigw_http_event.json @@ -8,8 +8,9 @@ "cookie2" ], "headers": { - "Header1": "value1", - "Header2": "value1,value2" + "Header1": "Value1", + "Header2": "value1,value2", + "header1": "value1" }, "queryStringParameters": { "parameter1": "value1,value2", diff --git a/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json b/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json index 28f10c22..e7907d58 100644 --- a/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json +++ b/aws-lambda-java-tests/src/test/resources/apigw_rest_event.json @@ -4,8 +4,9 @@ "path": "/my/path", "httpMethod": "GET", "headers": { - "Header1": "value1", - "Header2": "value2" + "Header1": "Value1", + "Header2": "value2", + "header1": "value1" }, "multiValueHeaders": { "Header1": [ @@ -14,6 +15,10 @@ "Header2": [ "value1", "value2" + ], + "header1": [ + "value1", + "value11" ] }, "queryStringParameters": { diff --git a/aws-lambda-java-tests/src/test/resources/elb_event.json b/aws-lambda-java-tests/src/test/resources/elb_event.json index 23f599f4..59e314b7 100644 --- a/aws-lambda-java-tests/src/test/resources/elb_event.json +++ b/aws-lambda-java-tests/src/test/resources/elb_event.json @@ -9,6 +9,7 @@ "queryStringParameters": {}, "headers": { "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Accept": "application/json", "accept-encoding": "gzip", "accept-language": "en-US,en;q=0.5", "connection": "keep-alive",