use of org.eclipse.hono.adapter.mqtt.MappedMessage in project hono by eclipse.
the class HttpBasedMessageMapping method mapDownstreamMessage.
/**
* {@inheritDoc}
* <p>
* This implementation tries to look up the URL of the service endpoint to invoke in the
* adapter's <em>mapperEndpoints</em> using the value of the registration assertion's
* <em>mapper</em> property as the key.
* If a mapping endpoint configuration is found, an HTTP GET request is sent to the endpoint
* containing the original message's
* <ul>
* <li>payload in the request body,</li>
* <li>content type in the HTTP content-type header,</li>
* <li>topic name in the {@value MessageHelper#APP_PROPERTY_ORIG_ADDRESS} header and</li>
* <li>all properties from the registration assertion as headers.</li>
* </ul>
*
* @return A future indicating the mapping result.
* The future will be succeeded with the original unaltered message if no mapping
* URL could be found. The future will be succeeded with the message contained in the
* response body if the returned status code is 200.
* Otherwise, the future will be failed with a {@link ServerErrorException}.
*/
@Override
public Future<MappedMessage> mapDownstreamMessage(final MqttContext ctx, final ResourceIdentifier targetAddress, final RegistrationAssertion registrationInfo) {
Objects.requireNonNull(ctx);
Objects.requireNonNull(registrationInfo);
final Promise<MappedMessage> result = Promise.promise();
final String mapper = registrationInfo.getDownstreamMessageMapper();
if (Strings.isNullOrEmpty(mapper)) {
LOG.debug("no payload mapping configured for {}", ctx.authenticatedDevice());
result.complete(unmodifiedMappedMessage(ctx, targetAddress));
} else {
final MapperEndpoint mapperEndpoint = mqttProtocolAdapterProperties.getMapperEndpoint(mapper);
if (mapperEndpoint == null) {
LOG.debug("no mapping endpoint [name: {}] found for {}", mapper, ctx.authenticatedDevice());
result.complete(unmodifiedMappedMessage(ctx, targetAddress));
} else {
mapDownstreamMessageRequest(ctx, targetAddress, registrationInfo, mapperEndpoint, result);
}
}
return result.future();
}
use of org.eclipse.hono.adapter.mqtt.MappedMessage in project hono by eclipse.
the class HttpBasedMessageMapping method mapDownstreamMessageRequest.
private void mapDownstreamMessageRequest(final MqttContext ctx, final ResourceIdentifier targetAddress, final RegistrationAssertion registrationInfo, final MapperEndpoint mapperEndpoint, final Handler<AsyncResult<MappedMessage>> resultHandler) {
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
JsonObject.mapFrom(registrationInfo).forEach(property -> {
final Object value = property.getValue();
if (value instanceof String) {
// prevent strings from being enclosed in quotes
headers.add(property.getKey(), (String) value);
} else {
headers.add(property.getKey(), Json.encode(value));
}
});
headers.add(MessageHelper.APP_PROPERTY_ORIG_ADDRESS, ctx.message().topicName());
if (ctx.contentType() != null) {
headers.add(HttpHeaders.CONTENT_TYPE.toString(), ctx.contentType());
}
final Promise<MappedMessage> result = Promise.promise();
webClient.post(mapperEndpoint.getPort(), mapperEndpoint.getHost(), mapperEndpoint.getUri()).putHeaders(headers).ssl(mapperEndpoint.isTlsEnabled()).sendBuffer(ctx.message().payload(), httpResponseAsyncResult -> {
if (httpResponseAsyncResult.failed()) {
LOG.debug("failed to map message [origin: {}] using mapping service [host: {}, port: {}, URI: {}]", ctx.authenticatedDevice(), mapperEndpoint.getHost(), mapperEndpoint.getPort(), mapperEndpoint.getUri(), httpResponseAsyncResult.cause());
result.fail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, httpResponseAsyncResult.cause()));
} else {
final HttpResponse<Buffer> httpResponse = httpResponseAsyncResult.result();
if (httpResponse.statusCode() == HttpURLConnection.HTTP_OK) {
final Map<String, String> additionalProperties = new HashMap<>();
httpResponse.headers().forEach(entry -> additionalProperties.put(entry.getKey(), entry.getValue()));
final String mappedDeviceId = Optional.ofNullable(additionalProperties.remove(MessageHelper.APP_PROPERTY_DEVICE_ID)).map(id -> {
LOG.debug("original {} has been mapped to [device-id: {}]", ctx.authenticatedDevice(), id);
return id;
}).orElseGet(() -> targetAddress.getResourceId());
result.complete(new MappedMessage(ResourceIdentifier.from(targetAddress.getEndpoint(), targetAddress.getTenantId(), mappedDeviceId), httpResponse.bodyAsBuffer(), additionalProperties));
} else {
LOG.debug("mapping service [host: {}, port: {}, URI: {}] returned unexpected status code: {}", mapperEndpoint.getHost(), mapperEndpoint.getPort(), mapperEndpoint.getUri(), httpResponse.statusCode());
result.fail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "could not invoke configured mapping service"));
}
}
resultHandler.handle(result.future());
});
}
Aggregations