|
18 | 18 |
|
19 | 19 | import static io.netty.buffer.Unpooled.copiedBuffer; |
20 | 20 | import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION; |
21 | | -import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH; |
22 | 21 | import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; |
23 | 22 |
|
24 | 23 | import java.io.IOException; |
25 | 24 | import java.net.URI; |
| 25 | +import java.util.HashMap; |
26 | 26 | import java.util.List; |
27 | 27 | import java.util.Map; |
28 | 28 | import java.util.Map.Entry; |
29 | 29 |
|
30 | | -import io.netty.handler.codec.DecoderException; |
31 | 30 | import org.apache.cloudstack.storage.template.UploadEntity; |
32 | 31 | import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; |
33 | 32 | import org.apache.commons.lang3.StringUtils; |
|
41 | 40 | import io.netty.channel.ChannelFutureListener; |
42 | 41 | import io.netty.channel.ChannelHandlerContext; |
43 | 42 | import io.netty.channel.SimpleChannelInboundHandler; |
| 43 | +import io.netty.handler.codec.DecoderException; |
44 | 44 | import io.netty.handler.codec.http.DefaultFullHttpResponse; |
45 | 45 | import io.netty.handler.codec.http.FullHttpResponse; |
46 | 46 | import io.netty.handler.codec.http.HttpContent; |
@@ -79,16 +79,46 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj |
79 | 79 |
|
80 | 80 | private boolean requestProcessed = false; |
81 | 81 |
|
82 | | - private static final String HEADER_SIGNATURE = "x-signature"; |
83 | | - |
84 | | - private static final String HEADER_METADATA = "x-metadata"; |
| 82 | + enum UploadHeader { |
| 83 | + SIGNATURE("x-signature"), |
| 84 | + METADATA("x-metadata"), |
| 85 | + EXPIRES("x-expires"), |
| 86 | + HOST("x-forwarded-host"), |
| 87 | + CONTENT_LENGTH("content-length"); |
85 | 88 |
|
86 | | - private static final String HEADER_EXPIRES = "x-expires"; |
87 | | - |
88 | | - private static final String HEADER_HOST = "x-forwarded-host"; |
| 89 | + private final String name; |
| 90 | + UploadHeader(String name) { |
| 91 | + this.name = name; |
| 92 | + } |
| 93 | + public String getName() { |
| 94 | + return this.name; |
| 95 | + } |
| 96 | + public static UploadHeader fromName(String name) { |
| 97 | + for (UploadHeader type : values()) { |
| 98 | + if (type.getName().equalsIgnoreCase(name)) { |
| 99 | + return type; |
| 100 | + } |
| 101 | + } |
| 102 | + return null; |
| 103 | + } |
| 104 | + } |
89 | 105 |
|
90 | 106 | private static long processTimeout; |
91 | 107 |
|
| 108 | + protected Map<UploadHeader, String> getUploadRequestUsefulHeaders(HttpHeaders headers) { |
| 109 | + Map<UploadHeader, String> headerMap = new HashMap<>(); |
| 110 | + for (Entry<String, String> entry : headers) { |
| 111 | + UploadHeader headerType = UploadHeader.fromName(entry.getKey()); |
| 112 | + if (headerType != null) { |
| 113 | + headerMap.put(headerType, entry.getValue()); |
| 114 | + } |
| 115 | + } |
| 116 | + for (UploadHeader type : UploadHeader.values()) { |
| 117 | + logger.info(String.format("HEADER: %s=%s", type, headerMap.get(type))); |
| 118 | + } |
| 119 | + return headerMap; |
| 120 | + } |
| 121 | + |
92 | 122 | public HttpUploadServerHandler(NfsSecondaryStorageResource storageResource) { |
93 | 123 | this.storageResource = storageResource; |
94 | 124 | } |
@@ -123,46 +153,19 @@ public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Excep |
123 | 153 |
|
124 | 154 | URI uri = new URI(request.getUri()); |
125 | 155 |
|
126 | | - String signature = null; |
127 | | - String expires = null; |
128 | | - String metadata = null; |
129 | | - String hostname = null; |
130 | | - long contentLength = 0; |
131 | | - |
132 | | - for (Entry<String, String> entry : request.headers()) { |
133 | | - switch (entry.getKey()) { |
134 | | - case HEADER_SIGNATURE: |
135 | | - signature = entry.getValue(); |
136 | | - break; |
137 | | - case HEADER_METADATA: |
138 | | - metadata = entry.getValue(); |
139 | | - break; |
140 | | - case HEADER_EXPIRES: |
141 | | - expires = entry.getValue(); |
142 | | - break; |
143 | | - case HEADER_HOST: |
144 | | - hostname = entry.getValue(); |
145 | | - break; |
146 | | - case HttpHeaders.Names.CONTENT_LENGTH: |
147 | | - contentLength = Long.parseLong(entry.getValue()); |
148 | | - break; |
149 | | - } |
150 | | - } |
151 | | - logger.info("HEADER: signature=" + signature); |
152 | | - logger.info("HEADER: metadata=" + metadata); |
153 | | - logger.info("HEADER: expires=" + expires); |
154 | | - logger.info("HEADER: hostname=" + hostname); |
155 | | - logger.info("HEADER: content-length=" + contentLength); |
| 156 | + Map<UploadHeader, String> headers = getUploadRequestUsefulHeaders(request.headers()); |
| 157 | + long contentLength = headers.get(UploadHeader.CONTENT_LENGTH) != null ? Long.parseLong(headers.get(UploadHeader.CONTENT_LENGTH)) : 0; |
156 | 158 | QueryStringDecoder decoderQuery = new QueryStringDecoder(uri); |
157 | 159 | Map<String, List<String>> uriAttributes = decoderQuery.parameters(); |
158 | 160 | uuid = uriAttributes.get("uuid").get(0); |
159 | 161 | logger.info("URI: uuid=" + uuid); |
160 | 162 | UploadEntity uploadEntity = null; |
161 | 163 | try { |
162 | 164 | // Validate the request here |
163 | | - storageResource.validatePostUploadRequest(signature, metadata, expires, hostname, contentLength, uuid); |
| 165 | + storageResource.validatePostUploadRequest(headers.get(UploadHeader.SIGNATURE), headers.get(UploadHeader.METADATA), |
| 166 | + headers.get(UploadHeader.EXPIRES), headers.get(UploadHeader.HOST), contentLength, uuid); |
164 | 167 | //create an upload entity. This will fail if entity already exists. |
165 | | - uploadEntity = storageResource.createUploadEntity(uuid, metadata, contentLength); |
| 168 | + uploadEntity = storageResource.createUploadEntity(uuid, headers.get(UploadHeader.METADATA), contentLength); |
166 | 169 | } catch (InvalidParameterValueException ex) { |
167 | 170 | logger.error("post request validation failed", ex); |
168 | 171 | responseContent.append(ex.getMessage()); |
@@ -280,7 +283,7 @@ private void writeResponse(Channel channel, HttpResponseStatus statusCode) { |
280 | 283 | response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8"); |
281 | 284 | if (!close) { |
282 | 285 | // There's no need to add 'content-length' header if this is the last response. |
283 | | - response.headers().set(CONTENT_LENGTH, buf.readableBytes()); |
| 286 | + response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, buf.readableBytes()); |
284 | 287 | } |
285 | 288 | // Write the response. |
286 | 289 | ChannelFuture future = channel.writeAndFlush(response); |
|
0 commit comments