org.refcodes.web.HttpClientRequest Maven / Gradle / Ivy
package org.refcodes.web;
import java.util.HashMap;
import java.util.Map;
import org.refcodes.exception.MarshalException;
import org.refcodes.struct.PathMap;
import org.refcodes.textual.VerboseTextBuilder;
import org.refcodes.web.HttpBodyAccessor.HttpBodyProvider;
import org.refcodes.web.RedirectDepthAccessor.RedirectDepthProperty;
/**
* Defines a {@link HttpClientRequest} being the request as produced by the
* client.
*/
public class HttpClientRequest extends AbstractHttpRequest implements HttpBodyProvider, RedirectDepthProperty {
// /////////////////////////////////////////////////////////////////////////
// CONSTANTS:
// /////////////////////////////////////////////////////////////////////////
public static final int DEFAULT_REDIRECT_DEPTH = -1; // RetryCount.NORM.getValue();
// /////////////////////////////////////////////////////////////////////////
// VARIABLES:
// /////////////////////////////////////////////////////////////////////////
protected MediaTypeFactoryLookup _mediaTypeFactoryLookup;
private int _redirectDepth = DEFAULT_REDIRECT_DEPTH;
private Object _request = null;
// /////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS:
// /////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new http client request impl.
*
* @param aHttpMethod the http method
* @param aUrl The {@link Url} from which to take the URL specific data.
* @param aMediaTypeFactoryLookup the media type factory lookup
*/
public HttpClientRequest( HttpMethod aHttpMethod, Url aUrl, MediaTypeFactoryLookup aMediaTypeFactoryLookup ) {
this( aHttpMethod, aUrl, null, DEFAULT_REDIRECT_DEPTH, aMediaTypeFactoryLookup );
}
/**
* Instantiates a new http client request impl.
*
* @param aHttpMethod the http method
* @param aUrl The {@link Url} from which to take the URL specific data.
* @param aRequest the request
* @param aMediaTypeFactoryLookup the media type factory lookup
*/
public HttpClientRequest( HttpMethod aHttpMethod, Url aUrl, Object aRequest, MediaTypeFactoryLookup aMediaTypeFactoryLookup ) {
this( aHttpMethod, aUrl, null, aRequest, DEFAULT_REDIRECT_DEPTH, aMediaTypeFactoryLookup );
}
/**
* Instantiates a new http client request impl.
*
* @param aHttpMethod the http method
* @param aUrl The {@link Url} from which to take the URL specific data.
* @param aHeaderFields the Header-Fields
* @param aRequest the request
* @param aMediaTypeFactoryLookup the media type factory lookup
*/
public HttpClientRequest( HttpMethod aHttpMethod, Url aUrl, RequestHeaderFields aHeaderFields, Object aRequest, MediaTypeFactoryLookup aMediaTypeFactoryLookup ) {
this( aHttpMethod, aUrl, aHeaderFields, aRequest, DEFAULT_REDIRECT_DEPTH, aMediaTypeFactoryLookup );
}
/**
* Instantiates a new http client request impl.
*
* @param aHttpMethod the http method
* @param aUrl The {@link Url} from which to take the URL specific data.
* @param aRedirectDepth The redirect depth provides the count of
* HTTP-Request and HTTP-Response cycles where the response
* represents a redirect as of
* {@link HttpStatusCode#isRedirectStatus()}. A value of -1
* represents a nearly infinite HTTP-Request and HTTP-Response cycle
* (infinite might mean a maximum of 256 cycle).
* @param aMediaTypeFactoryLookup the media type factory lookup
*/
public HttpClientRequest( HttpMethod aHttpMethod, Url aUrl, int aRedirectDepth, MediaTypeFactoryLookup aMediaTypeFactoryLookup ) {
this( aHttpMethod, aUrl, null, aRedirectDepth, aMediaTypeFactoryLookup );
}
/**
* Instantiates a new http client request impl.
*
* @param aHttpMethod the http method
* @param aUrl The {@link Url} from which to take the URL specific data.
* @param aRequest the request
* @param aRedirectDepth The redirect depth provides the count of
* HTTP-Request and HTTP-Response cycles where the response
* represents a redirect as of
* {@link HttpStatusCode#isRedirectStatus()}. A value of -1
* represents a nearly infinite HTTP-Request and HTTP-Response cycle
* (infinite might mean a maximum of 256 cycle).
* @param aMediaTypeFactoryLookup the media type factory lookup
*/
public HttpClientRequest( HttpMethod aHttpMethod, Url aUrl, Object aRequest, int aRedirectDepth, MediaTypeFactoryLookup aMediaTypeFactoryLookup ) {
this( aHttpMethod, aUrl, null, aRequest, aRedirectDepth, aMediaTypeFactoryLookup );
}
/**
* Instantiates a new http client request impl.
*
* @param aHttpMethod the http method
* @param aUrl The {@link Url} from which to take the URL specific data.
* @param aHeaderFields the Header-Fields
* @param aRequest the request
* @param aRedirectDepth The redirect depth provides the count of
* HTTP-Request and HTTP-Response cycles where the response
* represents a redirect as of
* {@link HttpStatusCode#isRedirectStatus()}. A value of -1 keeps a
* redirect depth as used by default by underlying implementations.
* @param aMediaTypeFactoryLookup the media type factory lookup
*/
public HttpClientRequest( HttpMethod aHttpMethod, Url aUrl, RequestHeaderFields aHeaderFields, Object aRequest, int aRedirectDepth, MediaTypeFactoryLookup aMediaTypeFactoryLookup ) {
super( aHttpMethod, aUrl, aHeaderFields );
_mediaTypeFactoryLookup = aMediaTypeFactoryLookup;
_redirectDepth = aRedirectDepth;
setRequest( aRequest );
}
// /////////////////////////////////////////////////////////////////////////
// METHODS:
// /////////////////////////////////////////////////////////////////////////
/**
* Retrieves the request from the request property.
*
* @param the generic type
*
* @return The request stored by the request property.
*/
@SuppressWarnings("unchecked")
public REQ getRequest() {
return (REQ) _request;
}
/**
* Sets the request for the request property. The
* {@link HttpClientRequest#setRequest(Object)} supports the
* {@link HttpBodyMap} to marshal an {@link HttpBodyMap} into an HTTP
* Request-Body.
*
* @param the generic type
* @param aRequest The request to be stored by the request property.
*/
public void setRequest( REQ aRequest ) {
_request = aRequest;
if ( aRequest != null && getHeaderFields() != null && getHeaderFields().getContentType() == null ) {
getHeaderFields().putContentType( toPreferredContentType() );
}
}
/**
* Automatically sets the {@link ContentType} to the
* {@link RequestHeaderFields} retrieved from {@link #getHeaderFields()}.
* (see
* {@link RequestHeaderFields#putContentType(org.refcodes.web.HttpMediaType)}
* )
*
* {@inheritDoc}
*/
@Override
public String toHttpBody() throws BadRequestException {
if ( _request == null ) {
return null;
}
Map theProperties = null;
final ContentType theContentType = toPreferredContentType();
final MediaTypeFactory theFactory = _mediaTypeFactoryLookup.toMediaTypeFactory( theContentType.getMediaType() );
final String theCharset = theContentType.getCharsetParametrer();
if ( theCharset != null ) {
theProperties = new HashMap<>();
theProperties.put( MediaTypeParameter.CHARSET.getName(), theCharset );
}
if ( theFactory == null ) {
throw new BadRequestException( "No Media-Type factory found (added) for request's Media-Type <" + theContentType + "> (raw requested Media-Type is <" + getHeaderFields().get( HeaderField.CONTENT_TYPE ) + ">)" );
}
try {
// HttpModyMap support |-->
Object theRequest = _request;
if ( _request instanceof PathMap ) {
theRequest = ( (PathMap>) _request ).toDataStructure();
}
// HttpModyMap support <--|
return theFactory.toMarshaled( theRequest, theProperties );
}
catch ( MarshalException e ) {
throw new BadRequestException( "Unable to marshal request <" + getRequest() + "> to request's Media-Type <" + new VerboseTextBuilder().toString( theFactory.getMediaTypes() ) + ">.", e );
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return getClass().getName() + " [httpMethod=" + _httpMethod + ", url=" + _url + "]";
}
// /////////////////////////////////////////////////////////////////////////
// HELPER:
// /////////////////////////////////////////////////////////////////////////
/**
* Determines the preferred Content-Type by evaluating the Content-Type
* Header-Field and the supported {@link MediaTypeFactory} instances and
* taking the request into account. Depending on the evaluation, a
* Content-Type might be set by this method if none has been set before.
*
* @return The preferred {@link ContentType}.
*/
private ContentType toPreferredContentType() {
ContentType theContentType = getHeaderFields().getContentType();
if ( theContentType == null ) {
// |--> Do we have Form-Fields? Use "x-www-form-urlencoded"!
if ( _request instanceof FormFields && _mediaTypeFactoryLookup.hasMediaTypeFactory( MediaType.APPLICATION_X_WWW_FORM_URLENCODED ) ) {
return MediaType.APPLICATION_X_WWW_FORM_URLENCODED.toContentType();
}
// Do we have Form-Fields? Use "x-www-form-urlencoded"! <--|
final MediaType[] theMediaTypes = _mediaTypeFactoryLookup.getFactoryMediaTypes();
if ( theMediaTypes != null && theMediaTypes.length != 0 ) {
getHeaderFields().putContentType( theMediaTypes[0] );
theContentType = new ContentType( theMediaTypes[0] );
}
}
return theContentType;
}
/**
* {@inheritDoc}
*/
@Override
public int getRedirectDepth() {
return _redirectDepth;
}
/**
* {@inheritDoc}
*/
@Override
public void setRedirectDepth( int aRedirectDepth ) {
_redirectDepth = aRedirectDepth;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy