org.apache.shindig.gadgets.http.HttpRequest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shindig-gadgets Show documentation
Show all versions of shindig-gadgets Show documentation
Renders gadgets, provides the gadget metadata service, and serves
all javascript required by the OpenSocial specification.
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.shindig.gadgets.http;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shindig.auth.SecurityToken;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.common.util.CharsetUtil;
import org.apache.shindig.config.ContainerConfig;
import org.apache.shindig.gadgets.AuthType;
import org.apache.shindig.gadgets.oauth.OAuthArguments;
import org.apache.shindig.gadgets.oauth2.OAuth2Arguments;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Creates HttpRequests. A new HttpRequest should be created for every unique HttpRequest
* being constructed.
*/
public class HttpRequest {
/** Automatically added to every request so that we know that the request came from our server. */
public static final String DOS_PREVENTION_HEADER = "X-shindig-dos";
static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded; charset=utf-8";
private String method = "GET";
private Uri uri;
private final Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
// Internal parameters which serve as extra information to pass along the
// chain of HttpRequest processing.
// NOTE: These are not get/post parameter equivalent of HttpServletRequest.
private final Map params = Maps.newHashMap();
private byte[] postBody = ArrayUtils.EMPTY_BYTE_ARRAY;
// TODO: It might be useful to refactor these into a simple map of objects and use sub classes
// for more detailed data.
// Cache control.
private boolean ignoreCache;
private int cacheTtl = -1;
// Sanitization
private boolean sanitizationRequested;
// Caja
private boolean cajaRequested;
// Whether to follow redirects
private boolean followRedirects = true;
// Context for the request.
private Uri gadget;
private String container = ContainerConfig.DEFAULT_CONTAINER;
// For signed fetch & OAuth
private SecurityToken securityToken;
// TODO: Move this into OAuthRequest.
private OAuthArguments oauthArguments;
private OAuth2Arguments oauth2Arguments;
private AuthType authType;
private String rewriteMimeType;
/**
* Construct a new request for the given uri.
*/
public HttpRequest(Uri uri) {
this.uri = uri;
authType = AuthType.NONE;
addHeader(DOS_PREVENTION_HEADER, "on");
}
/**
* Clone an existing HttpRequest.
*/
public HttpRequest(HttpRequest request) {
method = request.method;
uri = request.uri;
headers.putAll(request.headers);
postBody = request.postBody;
ignoreCache = request.ignoreCache;
cacheTtl = request.cacheTtl;
gadget = request.gadget;
container = request.container;
securityToken = request.securityToken;
if (request.oauthArguments != null) {
oauthArguments = new OAuthArguments(request.oauthArguments);
}
if (request.oauth2Arguments != null) {
oauth2Arguments = new OAuth2Arguments(request.oauth2Arguments);
}
authType = request.authType;
rewriteMimeType = request.rewriteMimeType;
followRedirects = request.followRedirects;
}
public HttpRequest setMethod(String method) {
this.method = method;
return this;
}
public HttpRequest setUri(Uri uri) {
this.uri = uri;
return this;
}
/**
* Add a single header to the request. If a value for the given name is already set, a second
* value is added. If you wish to overwrite any possible values for a header, use
* {@link #setHeader(String, String)}.
*/
public HttpRequest addHeader(String name, String value) {
List values = headers.get(name);
if (values == null) {
values = Lists.newArrayList();
headers.put(name, values);
}
values.add(value);
return this;
}
/**
* Sets a single header value, overwriting any previously set headers with the same name.
*/
public HttpRequest setHeader(String name, String value) {
headers.put(name, Lists.newArrayList(value));
return this;
}
/**
* Adds an entire map of headers to the request.
*/
public HttpRequest addHeaders(Map headers) {
for (Map.Entry entry : headers.entrySet()) {
addHeader(entry.getKey(), entry.getValue());
}
return this;
}
/**
* Adds all headers in the provided map to the request.
*/
public HttpRequest addAllHeaders(Map> headers) {
this.headers.putAll(headers);
return this;
}
/**
* Remove all headers with the given name from the request.
*
* @return Any values that were removed from the request.
*/
public List removeHeader(String name) {
return headers.remove(name);
}
/**
* Assigns the specified body to the request, copying all input bytes.
*/
public HttpRequest setPostBody(byte[] postBody) {
if (postBody == null) {
this.postBody = ArrayUtils.EMPTY_BYTE_ARRAY;
} else {
this.postBody = new byte[postBody.length];
System.arraycopy(postBody, 0, this.postBody, 0, postBody.length);
}
return this;
}
/**
* Fills in the request body from an InputStream.
*/
public HttpRequest setPostBody(InputStream is) throws IOException {
postBody = IOUtils.toByteArray(is);
return this;
}
/**
* @param ignoreCache Whether to ignore all caching for this request.
*/
public HttpRequest setIgnoreCache(boolean ignoreCache) {
this.ignoreCache = ignoreCache;
if (ignoreCache) {
// Bypass any proxy caches as well.
headers.put("Pragma", Lists.newArrayList("no-cache"));
}
return this;
}
/**
* Should content fetched in response to this request
* be sanitized based on the specified mime-type
*/
public boolean isSanitizationRequested() {
return sanitizationRequested;
}
public void setSanitizationRequested(boolean sanitizationRequested) {
this.sanitizationRequested = sanitizationRequested;
}
/**
* Should content fetched in response to this request
* be sanitized based on the specified mime-type
*/
public boolean isCajaRequested() {
return cajaRequested;
}
public void setCajaRequested(boolean cajaRequested) {
this.cajaRequested = cajaRequested;
}
/**
* @param cacheTtl The amount of time to cache the result object for, in seconds. If set to -1,
* HTTP cache control headers will be honored. Otherwise objects will be cached for the time
* specified.
*/
public HttpRequest setCacheTtl(int cacheTtl) {
this.cacheTtl = cacheTtl;
return this;
}
/**
* @param gadget The gadget that caused this HTTP request to be necessary. May be null if the
* request was not initiated by the actions of a gadget.
*/
public HttpRequest setGadget(Uri gadget) {
this.gadget = gadget;
return this;
}
/**
* @param container The container that this request originated from.
*/
public HttpRequest setContainer(String container) {
this.container = container;
return this;
}
/**
* Assign the security token to use for making any form of authenticated request.
*/
public HttpRequest setSecurityToken(SecurityToken securityToken) {
this.securityToken = securityToken;
return this;
}
/**
* @param oauthArguments arguments for OAuth/signed fetched
*/
public HttpRequest setOAuthArguments(OAuthArguments oauthArguments) {
this.oauthArguments = oauthArguments;
return this;
}
/**
* @param oauth2Arguments arguments for OAuth2/signed fetched
*/
public HttpRequest setOAuth2Arguments(OAuth2Arguments oauth2Arguments) {
this.oauth2Arguments = oauth2Arguments;
return this;
}
/**
* @param followRedirects whether this request should automatically follow redirects.
*/
public HttpRequest setFollowRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
return this;
}
/**
* @param authType The type of authentication being used for this request.
*/
public HttpRequest setAuthType(AuthType authType) {
this.authType = authType;
return this;
}
/**
* @param rewriteMimeType The assumed content type of the response to be rewritten. Overrides
* any values set in the Content-Type response header.
*
* TODO: Move this to new rewriting facility.
*/
public HttpRequest setRewriteMimeType(String rewriteMimeType) {
this.rewriteMimeType = rewriteMimeType;
return this;
}
public String getMethod() {
return method;
}
public Uri getUri() {
return uri;
}
/**
* @return All headers to be sent in this request.
*/
public Map> getHeaders() {
return headers;
}
/**
* @param name The header to fetch
* @return A list of headers with that name (may be empty).
*/
public List getHeaders(String name) {
List match = headers.get(name);
if (match == null) {
return Collections.emptyList();
} else {
return match;
}
}
/**
* @return The first set header with the given name or null if not set. If
* you need multiple values for the header, use getHeaders().
*/
public String getHeader(String name) {
List headerList = getHeaders(name);
if (headerList.isEmpty()) {
return null;
} else {
return headerList.get(0);
}
}
/**
* @return The content type of the request (determined from request headers)
*/
public String getContentType() {
String type = getHeader("Content-Type");
if (type == null) {
return DEFAULT_CONTENT_TYPE;
}
return type;
}
/**
* @return An input stream that can be used to read the post body.
*/
public InputStream getPostBody() {
return new ByteArrayInputStream(postBody);
}
/**
* @return The post body as a string, assuming UTF-8 encoding.
* TODO: We should probably tolerate other encodings, based on the
* Content-Type header.
*/
public String getPostBodyAsString() {
return CharsetUtil.newUtf8String(postBody);
}
/**
* Retrieves the total length of the post body.
*
* @return The length of the post body.
*/
public int getPostBodyLength() {
return postBody.length;
}
/**
* @return True if caching should be ignored for this request.
*/
public boolean getIgnoreCache() {
return ignoreCache;
}
/**
* @return The amount of time to cache any response objects for, in seconds.
*/
public int getCacheTtl() {
return cacheTtl;
}
/**
* @return The uri of gadget responsible for making this request.
*/
public Uri getGadget() {
return gadget;
}
public String getParam(String paramName) {
return params.get(paramName);
}
public Integer getParamAsInteger(String paramName) {
String value = params.get(paramName);
if (value == null) {
return null;
}
return NumberUtils.createInteger(value);
}
public void setParam(String paramName, T paramValue) {
params.put(paramName, (paramValue == null) ? null : String.valueOf(paramValue));
}
public Map getParams() {
return params;
}
/**
* @return The container responsible for making this request.
*/
public String getContainer() {
return container;
}
/**
* @return The security token used to make this request.
*/
public SecurityToken getSecurityToken() {
return securityToken;
}
/**
* @return arguments for OAuth and signed fetch
*/
public OAuthArguments getOAuthArguments() {
return oauthArguments;
}
/**
* @return arguments for OAuth2 and signed fetch
*/
public OAuth2Arguments getOAuth2Arguments() {
return oauth2Arguments;
}
/**
* @return true if redirects should be followed.
*/
public boolean getFollowRedirects() {
return followRedirects;
}
/**
* @return The type of authentication being used for this request.
*/
public AuthType getAuthType() {
return authType;
}
/**
* @return The content type to assume when rewriting.
*
* TODO: Move this to new rewriting facility.
*/
public String getRewriteMimeType() {
return rewriteMimeType;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(method);
buf.append(' ').append(uri.getPath())
.append(uri.getQuery() == null ? "" : '?' + uri.getQuery()).append("\n\n");
buf.append("Host: ").append(uri.getAuthority()).append('\n');
buf.append("X-Shindig-AuthType: ").append(authType).append('\n');
for (Map.Entry> entry : headers.entrySet()) {
String name = entry.getKey();
for (String value : entry.getValue()) {
buf.append(name).append(": ").append(value).append('\n');
}
}
buf.append('\n');
buf.append(getPostBodyAsString());
return buf.toString();
}
@Override
public int hashCode() {
return method.hashCode()
^ uri.hashCode()
^ authType.hashCode()
^ Arrays.hashCode(postBody)
^ headers.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof HttpRequest)) {
return false;
}
HttpRequest req = (HttpRequest)obj;
return method.equals(req.method) &&
uri.equals(req.uri) &&
authType == req.authType &&
Arrays.equals(postBody, req.postBody) &&
headers.equals(req.headers);
// TODO: Verify that other fields aren't meaningful. Especially important to check for oauth args.
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy