All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lumbermill.internal.http.PostHandler Maven / Gradle / Ivy

There is a newer version: 0.0.26
Show newest version
/*
 * Copyright 2016 Sony Mobile Communications, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 lumbermill.internal.http;

import com.fasterxml.jackson.core.JsonParseException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;

import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.ext.web.RoutingContext;
import lumbermill.api.Codecs;
import lumbermill.api.Codec;
import lumbermill.api.Event;
import lumbermill.http.HttpHandler;

public class PostHandler implements Handler {

    public interface OnPostCreatedCallback {
        void onCreated(T event);
    }

    public static final String EVENT_METADATA_HTTP_ROUTING_CONTEXT = "http.context";

    private static final Logger LOGGER = LoggerFactory.getLogger(PostHandler.class);
    private static final Map codecs = new HashMap() {
        {
            put("application/json", Codecs.JSON_ANY);
            put("text/plain", Codecs.TEXT_TO_JSON);
            put("default", Codecs.TEXT_TO_JSON);
        }
    };

    private final Optional>> codec;
    private final OnPostCreatedCallback callback;

    public PostHandler(Optional>> codec, OnPostCreatedCallback callback) {
        this.codec = codec;
        this.callback = callback;

    }

    public void handle(RoutingContext context) {
        try {
            String contentType = contentType(context.request());
            Codec codec = codecFor(contentType);

            LOGGER.trace("Using Content-Type {} and path {}", contentType, context.request().path());

            IN event = parseRequest(context, codec);
            if (event == null) {
                LOGGER.debug("Codec/Handler failed to return an Event from parse, Handler should have closed resources.");
            } else {
                callback.onCreated(event);
            }
        } catch (HttpHandler.HttpCodecException e) {
            LOGGER.warn("Codec failed to handle exception with reason {}", e.reason, e);
            context.fail(e.status);
        } catch (Exception e) {
            if (isUndefinedClientError(e)) {
                LOGGER.warn("Undefined client error, status:400", e);
                context.fail(400);
            } else {
                LOGGER.error("Unknown error, status:500", e);
                context.fail(500);
            }
        }

    }

    private boolean isUndefinedClientError(Exception e) {
        return e instanceof JsonParseException
                || e.getCause() instanceof JsonParseException
                || e instanceof IllegalArgumentException;
    }

    private IN parseRequest(RoutingContext context, Codec codec) {
        Buffer buffer = context.getBody();

        IN e;
        if (codec instanceof HttpHandler) {
            PostRequestImpl postRequest = new PostRequestImpl(context);
            context.put("postRequest", postRequest);

            e = ((HttpHandler) codec).parse(postRequest);

            context.put("httpHandler", codec);
        } else {
            e = codec.from(buffer.getBytes());
        }
        if (e != null) {
            extractRouteParamsAsMetadata(context, e);
            e.put(EVENT_METADATA_HTTP_ROUTING_CONTEXT, context);
        }
        return e;
    }

    private void extractRouteParamsAsMetadata(RoutingContext context, IN e) {
        List> entries = context.request().params().entries();
        entries.forEach(entry -> e.put(entry.getKey(), entry.getValue()));
    }

    private String contentType(HttpServerRequest request) {
        String contentType = request.getHeader("Content-Type");
        if (contentType == null) {
            LOGGER.trace("No Content-Type sent, using text/plain");
            contentType = "text/plain";
        }
        return contentType;
    }

    private Codec codecFor(String contentTypeHeader) {
        Codec codec;
        if (this.codec.isPresent()) {
            // Create new Codec
            codec = this.codec.get().get();
        } else {
            codec = codecs.containsKey(contentTypeHeader) ?
                    codecs.get(contentTypeHeader) :
                    codecs.get("default");
        }
        return codec;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy