use of org.eclipse.californium.proxy2.http.ContentTypedEntity in project californium by eclipse.
the class Http2CoapTranslator method getCoapRequest.
/**
* Gets the coap request.
*
* Creates the CoAP request from the HTTP method and mapping it through the
* properties file. The URI is translated by extracting the part after the
* provided httpResource.
* (http://proxyname.domain:80/proxy/coap://coapserver:5683/resource
* converted in coap://coapserver:5683/resource.) It support proxy requests
* or request mapped to a local coap-server. It also support http-request
* send to this proxy using the http-proxy function itself. Though the
* primary scheme maybe tested to be http/https, the destination scheme must
* The method uses a decoder to translate the
* application/x-www-form-urlencoded format of the uri. The CoAP options are
* set translating the headers. If the HTTP message has an enclosing entity,
* it is converted to create the payload of the CoAP message; finally the
* content-type is set accordingly to the header and to the entity type.
*
* @param httpRequest the http request
* @param httpResource the http resource, if present in the uri, indicates
* the need of forwarding for the current request
* @param proxyingEnabled {@code true} to forward the request using the
* sub-path as URI, {@code false} to access a local coap
* resource.
* @return the coap request
* @throws TranslationException the translation exception
* @throws NullPointerException if one of the provided arguments is
* {@code null}.
*/
public Request getCoapRequest(Message<HttpRequest, ContentTypedEntity> httpRequest, String httpResource, boolean proxyingEnabled) throws TranslationException {
if (httpRequest == null) {
throw new NullPointerException("httpRequest must not be null!");
}
if (httpResource == null) {
throw new NullPointerException("httpResource must not be null!");
}
// get the http method
String httpMethod = httpRequest.getHead().getMethod();
// get the coap method
Code code = httpTranslator.getCoapCode(httpMethod);
// create the request -- since HTTP is reliable use CON
Request coapRequest = new Request(code, Type.CON);
// get the uri
URI uri;
try {
uri = httpRequest.getHead().getUri();
LOGGER.debug("URI <= '{}'", uri);
} catch (URISyntaxException ex) {
throw new TranslationException("Malformed uri: " + ex.getMessage());
}
if (!httpResource.startsWith("/")) {
httpResource = "/" + httpResource;
}
// if the uri contains the proxy resource name, the request should be
// forwarded and it is needed to get the real requested coap server's
// uri e.g.:
// /proxy/coap://vslab-dhcp-17.inf.ethz.ch:5684/helloWorld
// proxy resource: /proxy
// coap server: coap://vslab-dhcp-17.inf.ethz.ch:5684
// coap resource: helloWorld
String path = uri.getPath();
LOGGER.debug("URI path => '{}'", path);
if (path.startsWith(httpResource + "/")) {
path = path.substring(httpResource.length() + 1);
String target = path;
if (uri.getQuery() != null) {
target = path + "?" + uri.getQuery();
}
int index = target.indexOf(":/");
if (index > 0) {
// "coap://host" may have been normalized to "coap:/host"
index += 2;
if (target.charAt(index) != '/') {
// add /
target = target.substring(0, index) + "/" + target.substring(index);
}
}
try {
uri = new URI(target);
if (proxyingEnabled) {
// if the uri hasn't the indication of the scheme, add it
if (uri.getScheme() == null) {
throw new InvalidFieldException("Malformed uri: destination scheme missing! Use http://<proxy-host>" + httpResource + "/coap://<destination-host>/<path>");
}
// the uri will be set as a proxy-uri option
LOGGER.debug("URI destination => '{}'", target);
coapRequest.getOptions().setProxyUri(target);
} else {
if (uri.getScheme() != null) {
throw new InvalidFieldException("Malformed uri: local destination doesn't support scheme! Use http://<proxy-host>" + httpResource + "/<path>");
}
// the uri will be set as a coap-uri
target = "coap://localhost/" + target;
LOGGER.debug("URI local => '{}'", target);
coapRequest.setURI(target);
}
} catch (URISyntaxException e) {
LOGGER.warn("Malformed destination uri", e);
throw new InvalidFieldException("Malformed destination uri: " + target + "!");
}
} else if (proxyingEnabled && path.equals(httpResource)) {
String target = null;
if (uri.getQuery() != null) {
List<NameValuePair> query = WWWFormCodec.parse(uri.getQuery(), StandardCharsets.UTF_8);
for (NameValuePair arg : query) {
if (arg.getName().equalsIgnoreCase("target_uri")) {
target = arg.getValue();
break;
}
}
}
if (target == null) {
throw new InvalidFieldException("Malformed uri: target_uri is missing! Use http://<proxy-host>" + httpResource + "?target_uri=coap://<destination-host>/<path>");
}
try {
uri = new URI(target);
// if the uri hasn't the indication of the scheme, add it
if (uri.getScheme() == null) {
throw new InvalidFieldException("Malformed uri: destination scheme missing! Use http://<proxy-host>" + httpResource + "?target_uri=coap://<destination-host>/<path>");
}
// the uri will be set as a proxy-uri option
LOGGER.debug("URI destination => '{}'", target);
coapRequest.getOptions().setProxyUri(target);
} catch (URISyntaxException e) {
LOGGER.warn("Malformed destination uri", e);
throw new InvalidFieldException("Malformed destination uri: " + target + "!");
}
} else if (proxyingEnabled && uri.getScheme() != null) {
// http-server configured as http-proxy
int index = path.lastIndexOf('/');
if (0 < index) {
String scheme = path.substring(index + 1);
if (scheme.matches("\\w+:$")) {
scheme = scheme.substring(0, scheme.length() - 1);
path = path.substring(0, index);
try {
URI destination = new URI(scheme, null, uri.getHost(), uri.getPort(), path, uri.getQuery(), null);
coapRequest.getOptions().setProxyUri(destination.toASCIIString());
} catch (URISyntaxException e) {
LOGGER.debug("Malformed proxy uri", e);
throw new TranslationException("Malformed proxy uri: '" + uri + "' " + e.getMessage());
}
} else {
throw new TranslationException("Malformed proxy uri: target scheme missing! Use http://<destination-host>/<path>/<target-scheme>:");
}
} else {
throw new TranslationException("Malformed proxy uri: target scheme missing! Use http://<destination-host>/<path>/<target-scheme>:");
}
} else {
throw new IllegalArgumentException("URI '" + uri + "' doesn't match handler '" + httpResource + "'!");
}
// translate the http headers in coap options
List<Option> coapOptions = httpTranslator.getCoapOptions(httpRequest.getHead().getHeaders(), etagTranslator);
coapRequest.getOptions().addOptions(coapOptions);
// set the payload if the http entity is present
ContentTypedEntity entity = httpRequest.getBody();
httpTranslator.setCoapPayload(entity, coapRequest);
return coapRequest;
}
use of org.eclipse.californium.proxy2.http.ContentTypedEntity in project californium by eclipse.
the class ProxyHttpClientResource method handleRequest.
@Override
public void handleRequest(final Exchange exchange) {
final Request incomingCoapRequest = exchange.getRequest();
URI destination;
try {
InetSocketAddress exposedInterface = translator.getExposedInterface(incomingCoapRequest);
destination = translator.getDestinationURI(incomingCoapRequest, exposedInterface);
} catch (TranslationException ex) {
LOGGER.debug("URI error.", ex);
Response response = new Response(Coap2CoapTranslator.STATUS_FIELD_MALFORMED);
response.setPayload(ex.getMessage());
exchange.sendResponse(response);
return;
}
final CacheKey cacheKey;
final CacheResource cache = getCache();
if (cache != null) {
cacheKey = new CacheKey(incomingCoapRequest.getCode(), destination, incomingCoapRequest.getOptions().getAccept(), incomingCoapRequest.getPayload());
Response response = cache.getResponse(cacheKey);
StatsResource statsResource = getStatsResource();
if (statsResource != null) {
statsResource.updateStatistics(destination, response != null);
}
if (response != null) {
LOGGER.info("Cache returned {}", response);
exchange.sendResponse(response);
return;
}
} else {
cacheKey = null;
}
ProxyRequestProducer httpRequest = null;
try {
// get the mapping to http for the incoming coap request
httpRequest = translator.getHttpRequest(destination, incomingCoapRequest);
LOGGER.debug("Outgoing http request: {}", httpRequest.getRequestLine());
} catch (InvalidFieldException e) {
LOGGER.debug("Problems during the http/coap translation: {}", e.getMessage());
exchange.sendResponse(new Response(Coap2CoapTranslator.STATUS_FIELD_MALFORMED));
return;
} catch (TranslationException e) {
LOGGER.debug("Problems during the http/coap translation: {}", e.getMessage());
exchange.sendResponse(new Response(Coap2CoapTranslator.STATUS_TRANSLATION_ERROR));
return;
}
if (accept) {
exchange.sendAccept();
}
asyncClient.execute(httpRequest, new BasicResponseConsumer<ContentTypedEntity>(new ContentTypedEntityConsumer()), new BasicHttpContext(), new FutureCallback<Message<HttpResponse, ContentTypedEntity>>() {
@Override
public void completed(Message<HttpResponse, ContentTypedEntity> result) {
StatusLine status = new StatusLine(result.getHead());
try {
long timestamp = ClockUtil.nanoRealtime();
LOGGER.debug("Incoming http response: {}", status);
// the entity of the response, if non repeatable,
// could be
// consumed only one time, so do not debug it!
// System.out.println(EntityUtils.toString(httpResponse.getEntity()));
// translate the received http response in a coap
// response
Response coapResponse = translator.getCoapResponse(result, incomingCoapRequest);
coapResponse.setNanoTimestamp(timestamp);
if (cache != null) {
cache.cacheResponse(cacheKey, coapResponse);
}
exchange.sendResponse(coapResponse);
} catch (InvalidFieldException e) {
LOGGER.debug("Problems during the http/coap translation: {}", e.getMessage());
exchange.sendResponse(new Response(Coap2CoapTranslator.STATUS_FIELD_MALFORMED));
} catch (TranslationException e) {
LOGGER.debug("Problems during the http/coap translation: {}", e.getMessage());
exchange.sendResponse(new Response(Coap2CoapTranslator.STATUS_TRANSLATION_ERROR));
} catch (Throwable e) {
LOGGER.debug("Error during the http/coap translation: {}", e.getMessage(), e);
exchange.sendResponse(new Response(Coap2CoapTranslator.STATUS_FIELD_MALFORMED));
}
LOGGER.debug("Incoming http response: {} processed!", status);
}
@Override
public void failed(Exception ex) {
LOGGER.debug("Failed to get the http response: {}", ex.getMessage(), ex);
if (ex instanceof SocketTimeoutException) {
exchange.sendResponse(new Response(ResponseCode.GATEWAY_TIMEOUT));
} else {
exchange.sendResponse(new Response(ResponseCode.BAD_GATEWAY));
}
}
@Override
public void cancelled() {
LOGGER.debug("Request canceled");
exchange.sendResponse(new Response(ResponseCode.SERVICE_UNAVAILABLE));
}
});
}
use of org.eclipse.californium.proxy2.http.ContentTypedEntity in project californium by eclipse.
the class CrossProtocolTranslator method setCoapPayload.
/**
* Method to map the http entity in a coherent payload for the coap message.
*
* The method simply gets the bytes from the entity and, if needed changes
* the charset of the obtained bytes to UTF-8.
*
* @param httpBody the http entity. May be {@code null} or empty.
* @param coapMessage the coap message
* @throws TranslationException the translation exception
* @throws NullPointerException if the coap-message is {@code null}
*/
public void setCoapPayload(ContentTypedEntity httpBody, Message coapMessage) throws TranslationException {
if (coapMessage == null) {
throw new NullPointerException("coap message must not be null!");
}
if (httpBody != null) {
byte[] payload = httpBody.getContent();
if (payload != null) {
ContentType contentType = httpBody.getContentType();
int coapContentType = getCoapMediaType(contentType.getMimeType());
coapMessage.getOptions().setContentFormat(coapContentType);
if (MediaTypeRegistry.isCharsetConvertible(coapContentType)) {
try {
// get the charset for the http entity
Charset httpCharset = contentType.getCharset();
// coap
if (httpCharset != null && !httpCharset.equals(UTF_8)) {
// translate the payload to the utf-8 charset
payload = convertCharset(payload, httpCharset, UTF_8);
}
} catch (UnsupportedCharsetException e) {
LOGGER.debug("Cannot get the content of the http entity: " + e.getMessage());
throw new TranslationException("Cannot get the content of the http entity", e);
}
}
coapMessage.setPayload(payload);
}
}
}
Aggregations