
org.jdrupes.httpcodec.protocols.http.HttpResponse Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of httpcodec Show documentation
Show all versions of httpcodec Show documentation
HTTP coders and decoders for non-blocking I/O
/*
* This file is part of the JDrupes non-blocking HTTP Codec
* Copyright (C) 2016, 2017 Michael N. Lipp
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this program; if not, see .
*/
package org.jdrupes.httpcodec.protocols.http;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.Optional;
import javax.activation.MimetypesFileTypeMap;
import static org.jdrupes.httpcodec.protocols.http.HttpConstants.*;
import org.jdrupes.httpcodec.protocols.http.HttpConstants.HttpStatus;
import org.jdrupes.httpcodec.types.Converters;
import org.jdrupes.httpcodec.types.MediaType;
/**
* Represents an HTTP response header.
*/
public class HttpResponse extends HttpMessageHeader {
private static MimetypesFileTypeMap typesMap = new MimetypesFileTypeMap();
private int statusCode = -1;
private String reasonPhrase;
private HttpRequest request;
public HttpResponse(HttpProtocol protocol, HttpStatus status,
boolean hasPayload) {
super(protocol, hasPayload);
setStatus(status);
}
public HttpResponse(HttpProtocol protocol, int statusCode,
String reasonPhrase, boolean hasPayload) {
super(protocol, hasPayload);
setStatusCode(statusCode);
setReasonPhrase(reasonPhrase);
}
/* (non-Javadoc)
* @see HttpMessageHeader#setField(org.jdrupes.httpcodec.fields.HttpField)
*/
@Override
public HttpResponse setField(HttpField> value) {
super.setField(value);
return this;
}
/* (non-Javadoc)
* @see HttpMessageHeader#setField(java.lang.String, java.lang.Object)
*/
@Override
public HttpResponse setField(String name, T value) {
super.setField(name, value);
return this;
}
/* (non-Javadoc)
* @see org.jdrupes.httpcodec.protocols.http.HttpMessageHeader#setHasPayload(boolean)
*/
@Override
public HttpResponse setHasPayload(boolean hasPayload) {
super.setHasPayload(hasPayload);
return this;
}
/**
* @return the responseCode
*/
public int statusCode() {
return statusCode;
}
/**
* @param statusCode the responseCode to set
* @return the response for easy chaining
*/
public HttpResponse setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
/**
* @return the reason phrase
*/
public String reasonPhrase() {
return reasonPhrase;
}
/**
* @param reasonPhrase the reason phrase to set
* @return the response for easy chaining
*/
public HttpResponse setReasonPhrase(String reasonPhrase) {
this.reasonPhrase = reasonPhrase;
return this;
}
/**
* Sets both status code and reason phrase from the given
* http status value.
*
* @param status the status value
* @return the response for easy chaining
*/
public HttpResponse setStatus(HttpStatus status) {
statusCode = status.statusCode();
reasonPhrase = status.reasonPhrase();
return this;
}
/**
* Convenience method for setting the "Content-Type" header using
* the given media type. Also sets the "has payload" flag.
*
* @param mediaType the media type
* @return the response for easy chaining
*/
public HttpResponse setContentType(MediaType mediaType) {
setField(HttpField.CONTENT_TYPE, mediaType);
setHasPayload(true);
return this;
}
/**
* Convenience method for setting the "Content-Type" header
* from the given values. Also sets the "has payload" flag.
*
* @param type the type
* @param subtype the subtype
* @return the response for easy chaining
* @throws ParseException if the values cannot be parsed
*/
public HttpResponse setContentType(String type, String subtype)
throws ParseException {
return setContentType(new MediaType(type, subtype));
}
/**
* A convenience method for setting the "Content-Type" header (usually
* of type "text") together with its charset parameter. Also sets
* the "has payload" flag.
*
* @param type the type
* @param subtype the subtype
* @param charset the charset
* @return the response for easy chaining
* @throws ParseException if the values cannot be parsed
*/
public HttpResponse setContentType(String type, String subtype,
String charset) throws ParseException {
return setContentType(MediaType.builder().setType(type, subtype)
.setParameter("charset", charset).build());
}
/**
* Convenience method for setting the "Content-Type" header using
* the path information of the given request. Also sets
* the "has payload" flag.
*
* @param requestUri the requested resource
* @return the response for easy chaining
*/
public HttpResponse setContentType(URI requestUri) {
MediaType mediaType = contentType(requestUri);
setField(HttpField.CONTENT_TYPE, mediaType);
setHasPayload(true);
return this;
}
/**
* Derives a media type from the given URI.
*
* @param requestUri the uri
* @return the media type
*/
public static MediaType contentType(URI requestUri) {
MediaType mediaType = new MediaType("application", "octet-stream");
while (requestUri.isOpaque()) {
// Maybe the scheme specific part is a "nested" URI...
try {
requestUri = new URI(requestUri.getSchemeSpecificPart());
} catch (URISyntaxException | NullPointerException e) {
return mediaType;
}
}
if (requestUri.getPath() == null) {
return mediaType;
}
String mimeTypeName = null;
try {
// probeContentType is most advanced, but may fail if it tries
// to look at the file's content (which doesn't exist).
mimeTypeName = Files.probeContentType(Paths.get(
requestUri.getPath()));
} catch (IOException e) {
// Fall Through
}
if (mimeTypeName == null) {
mimeTypeName = typesMap.getContentType(requestUri.getPath());
}
try {
mediaType = Converters.MEDIA_TYPE.fromFieldValue(mimeTypeName);
} catch (ParseException e) {
// Cannot happen
}
if ("text".equals(mediaType.topLevelType())) {
mediaType = MediaType.builder().from(mediaType)
.setParameter("charset", System.getProperty(
"file.encoding", "UTF-8")).build();
}
return mediaType;
}
/**
* A convenience method for setting the "Content-Length" header.
*
* @param length the length
* @return the response for easy chaining
*/
public HttpResponse setContentLength(long length) {
return setField(new HttpField<>(
HttpField.CONTENT_LENGTH, length, Converters.LONG));
}
/**
* Associates the response with the request that it responds to. This method
* is invoked by the request decoder when it creates the prepared
* response for a request. The relationship with the request is required
* because information from the request headers may be needed when encoding
* the response.
*
* @param request
* the request
* @return the response for easy chaining
* @see HttpRequest#setResponse(HttpResponse)
*/
public HttpResponse setRequest(HttpRequest request) {
this.request = request;
return this;
}
/**
* Returns the request that this response responds to.
*
* @return the request
* @see #setRequest(HttpRequest)
*/
public Optional request() {
return Optional.ofNullable(request);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy