/lib/src/org/apache/http/impl/entity/LaxContentLengthStrategy.java
Java | 135 lines | 81 code | 8 blank | 46 comment | 27 complexity | f52c40202a39a4faa347fcce0e541d14 MD5 | raw file
Possible License(s): GPL-3.0
1/* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 28package org.apache.http.impl.entity; 29 30import org.apache.http.Header; 31import org.apache.http.HeaderElement; 32import org.apache.http.HttpException; 33import org.apache.http.HttpMessage; 34import org.apache.http.ParseException; 35import org.apache.http.ProtocolException; 36import org.apache.http.entity.ContentLengthStrategy; 37import org.apache.http.params.HttpParams; 38import org.apache.http.params.CoreProtocolPNames; 39import org.apache.http.protocol.HTTP; 40 41/** 42 * The lax implementation of the content length strategy. This class will ignore 43 * unrecognized transfer encodings and malformed <code>Content-Length</code> 44 * header values if the {@link CoreProtocolPNames#STRICT_TRANSFER_ENCODING} 45 * parameter of the given message is not set or set to <code>false</code>. 46 * <p> 47 * This class recognizes "chunked" and "identitiy" transfer-coding only. 48 * <p> 49 * The following parameters can be used to customize the behavior of this class: 50 * <ul> 51 * <li>{@link org.apache.http.params.CoreProtocolPNames#STRICT_TRANSFER_ENCODING}</li> 52 * </ul> 53 * 54 * @since 4.0 55 */ 56public class LaxContentLengthStrategy implements ContentLengthStrategy { 57 58 public LaxContentLengthStrategy() { 59 super(); 60 } 61 62 public long determineLength(final HttpMessage message) throws HttpException { 63 if (message == null) { 64 throw new IllegalArgumentException("HTTP message may not be null"); 65 } 66 67 HttpParams params = message.getParams(); 68 boolean strict = params.isParameterTrue(CoreProtocolPNames.STRICT_TRANSFER_ENCODING); 69 70 Header transferEncodingHeader = message.getFirstHeader(HTTP.TRANSFER_ENCODING); 71 Header contentLengthHeader = message.getFirstHeader(HTTP.CONTENT_LEN); 72 // We use Transfer-Encoding if present and ignore Content-Length. 73 // RFC2616, 4.4 item number 3 74 if (transferEncodingHeader != null) { 75 HeaderElement[] encodings = null; 76 try { 77 encodings = transferEncodingHeader.getElements(); 78 } catch (ParseException px) { 79 throw new ProtocolException 80 ("Invalid Transfer-Encoding header value: " + 81 transferEncodingHeader, px); 82 } 83 if (strict) { 84 // Currently only chunk and identity are supported 85 for (int i = 0; i < encodings.length; i++) { 86 String encoding = encodings[i].getName(); 87 if (encoding != null && encoding.length() > 0 88 && !encoding.equalsIgnoreCase(HTTP.CHUNK_CODING) 89 && !encoding.equalsIgnoreCase(HTTP.IDENTITY_CODING)) { 90 throw new ProtocolException("Unsupported transfer encoding: " + encoding); 91 } 92 } 93 } 94 // The chunked encoding must be the last one applied RFC2616, 14.41 95 int len = encodings.length; 96 if (HTTP.IDENTITY_CODING.equalsIgnoreCase(transferEncodingHeader.getValue())) { 97 return IDENTITY; 98 } else if ((len > 0) && (HTTP.CHUNK_CODING.equalsIgnoreCase( 99 encodings[len - 1].getName()))) { 100 return CHUNKED; 101 } else { 102 if (strict) { 103 throw new ProtocolException("Chunk-encoding must be the last one applied"); 104 } 105 return IDENTITY; 106 } 107 } else if (contentLengthHeader != null) { 108 long contentlen = -1; 109 Header[] headers = message.getHeaders(HTTP.CONTENT_LEN); 110 if (strict && headers.length > 1) { 111 throw new ProtocolException("Multiple content length headers"); 112 } 113 for (int i = headers.length - 1; i >= 0; i--) { 114 Header header = headers[i]; 115 try { 116 contentlen = Long.parseLong(header.getValue()); 117 break; 118 } catch (NumberFormatException e) { 119 if (strict) { 120 throw new ProtocolException("Invalid content length: " + header.getValue()); 121 } 122 } 123 // See if we can have better luck with another header, if present 124 } 125 if (contentlen >= 0) { 126 return contentlen; 127 } else { 128 return IDENTITY; 129 } 130 } else { 131 return IDENTITY; 132 } 133 } 134 135}