1 package software.amazon.awssdk.crt.http; 2 3 import java.util.Arrays; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import software.amazon.awssdk.crt.http.HttpVersion; 8 import java.nio.charset.Charset; 9 import java.nio.ByteBuffer; 10 import java.util.Collections; 11 12 public class HttpRequestBase { 13 protected final static Charset UTF8 = java.nio.charset.StandardCharsets.UTF_8; 14 protected final static int BUFFER_INT_SIZE = 4; 15 protected List<HttpHeader> headers; 16 protected HttpRequestBodyStream bodyStream; 17 protected HttpVersion version = HttpVersion.HTTP_1_1; 18 protected String method; 19 protected String encodedPath; 20 21 /** 22 * Only used for create request from native side. 23 */ HttpRequestBase()24 protected HttpRequestBase() { 25 } 26 HttpRequestBase(HttpHeader[] headers, HttpRequestBodyStream bodyStream)27 protected HttpRequestBase(HttpHeader[] headers, HttpRequestBodyStream bodyStream) { 28 if (headers == null) { 29 throw new IllegalArgumentException("Headers can be empty, but can't be null"); 30 } 31 method = ""; 32 encodedPath = ""; 33 this.headers = new ArrayList<HttpHeader>(Arrays.asList(headers)); 34 this.bodyStream = bodyStream; 35 } 36 37 /** 38 * @hidden Requests are marshalled as follows: 39 * 40 * version is as int: [4-bytes BE] 41 * 42 * each string field is: [4-bytes BE] [variable length bytes specified 43 * by the previous field] 44 * 45 * Each request is then: [version][method][path][header name-value 46 * pairs] 47 * @return encoded blob of headers 48 */ marshalForJni()49 public byte[] marshalForJni() { 50 int size = 0; 51 size += BUFFER_INT_SIZE; /* version */ 52 size += BUFFER_INT_SIZE + method.length(); 53 byte[] pathBytes = encodedPath.getBytes(UTF8); 54 size += BUFFER_INT_SIZE + pathBytes.length; 55 56 for (HttpHeader header : headers) { 57 if (header.getNameBytes().length > 0) { 58 size += header.getNameBytes().length + header.getValueBytes().length + (BUFFER_INT_SIZE * 2); 59 } 60 } 61 62 ByteBuffer buffer = ByteBuffer.allocate(size); 63 buffer.putInt(version.getValue()); 64 buffer.putInt(method.length()); 65 buffer.put(method.getBytes(UTF8)); 66 buffer.putInt(pathBytes.length); 67 buffer.put(pathBytes); 68 69 for (HttpHeader header : headers) { 70 if (header.getNameBytes().length > 0) { 71 buffer.putInt(header.getNameBytes().length); 72 buffer.put(header.getNameBytes()); 73 buffer.putInt(header.getValueBytes().length); 74 buffer.put(header.getValueBytes()); 75 } 76 } 77 78 return buffer.array(); 79 } 80 getBodyStream()81 public HttpRequestBodyStream getBodyStream() { 82 return bodyStream; 83 } 84 getHeaders()85 public List<HttpHeader> getHeaders() { 86 return headers; 87 } 88 getHeadersAsArray()89 public HttpHeader[] getHeadersAsArray() { 90 return headers.toArray(new HttpHeader[] {}); 91 } 92 addHeader(final HttpHeader header)93 public void addHeader(final HttpHeader header) { 94 headers.add(header); 95 } 96 addHeader(final String headerName, final String headerValue)97 public void addHeader(final String headerName, final String headerValue) { 98 headers.add(new HttpHeader(headerName, headerValue)); 99 } 100 addHeaders(final HttpHeader[] headers)101 public void addHeaders(final HttpHeader[] headers) { 102 Collections.addAll(this.headers, headers); 103 104 } 105 } 106