/**
* Copyright 2016-2017 Sixt GmbH & Co. Autovermietung KG
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain a
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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 com.sixt.service.framework.jetty;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
@Singleton
public class RpcServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(RpcServlet.class);
public final static String CONTENT_TYPE = "Content-Type";
public final static String TYPE_JSON = "application/json";
public final static String TYPE_PROTO = "application/proto";
public final static String TYPE_OCTET = "application/octet-stream";
protected JsonHandler jsonRpcHandler;
protected ProtobufHandler protobufHandler;
protected AtomicBoolean canServeRequests = new AtomicBoolean(false);
@Inject
public RpcServlet(JsonHandler jsonHandler, ProtobufHandler protobufHandler) {
this.jsonRpcHandler = jsonHandler;
this.protobufHandler = protobufHandler;
}
public void serveRequests() {
canServeRequests.set(true);
}
@Override
protected void doHead(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
//return a 200, we are alive
//HEAD should do the same as GET, set all headers, but not provide the content
}
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
//What to do with GETs?
}
@Override
protected void doPost(HttpServletRequest req,
HttpServletResponse resp) throws ServletException, IOException {
if (! canServeRequests.get()) {
logger.info("Not processing request, service not ready yet");
resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
try {
//TODO: refactor and clean up. we should use codecs to abstract the encoding/decoding so that
// there is one handler class without a bunch of duplication
String contentType = req.getHeader(CONTENT_TYPE);
logger.debug("Request content-type: {}", contentType);
if (isProtobuf(contentType)) {
protobufHandler.doPost(req, resp);
} else if (isJson(contentType)) {
jsonRpcHandler.doPost(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
} catch (Exception ex) {
logger.error("Uncaught exception handling POST", ex);
}
}
private boolean isProtobuf(String ctype) {
if (ctype == null) {
return false;
}
return ctype.startsWith(TYPE_PROTO) || ctype.startsWith(TYPE_OCTET);
}
private boolean isJson(String ctype) {
if (ctype == null) {
return false;
}
return ctype.startsWith(TYPE_JSON);
}
}