TinyHttpHandler.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 net.morimekta.tiny.server.http;
- import com.sun.net.httpserver.HttpExchange;
- import com.sun.net.httpserver.HttpHandler;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.io.IOException;
- import java.lang.reflect.Method;
- import java.util.Set;
- import java.util.TreeSet;
- /**
- * Class simplifying the HttpHandler in a similar fashion to the jakarta
- * <code>HttpServlet</code> class. Just implement the matching method to
- * the HTTP method you need served.
- */
- public abstract class TinyHttpHandler implements HttpHandler {
- private static final Logger LOGGER = LoggerFactory.getLogger(TinyHttpHandler.class);
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- try {
- exchange.getResponseHeaders().set("Server", "tiny-server");
- switch (exchange.getRequestMethod()) {
- case "GET":
- doGet(exchange);
- break;
- case "POST":
- doPost(exchange);
- break;
- case "HEAD":
- doHead(exchange);
- break;
- case "OPTIONS":
- doOptions(exchange);
- break;
- case "TRACE":
- doTrace(exchange);
- break;
- case "PUT":
- doPut(exchange);
- break;
- case "DELETE":
- doDelete(exchange);
- break;
- default: {
- LOGGER.warn("Unknown request method: {} {} HTTP/1.1",
- exchange.getRequestMethod(),
- exchange.getRequestURI().getPath());
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, 0);
- }
- }
- } catch (Exception e) {
- if (exchange.getResponseCode() <= 0) {
- LOGGER.warn("Exception handling: {} {} HTTP/1.1",
- exchange.getRequestMethod(),
- exchange.getRequestURI().getPath(),
- e);
- exchange.sendResponseHeaders(TinyHttpStatus.SC_INTERNAL, 0);
- } else {
- LOGGER.error("Exception handling: {} {} HTTP/1.1",
- exchange.getRequestMethod(),
- exchange.getRequestURI().getPath(),
- e);
- }
- } finally {
- exchange.close();
- }
- }
- /**
- * Handle a GET request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doGet(HttpExchange exchange) throws IOException {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, 0);
- }
- /**
- * Handle a POST request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doPost(HttpExchange exchange) throws IOException {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, 0);
- }
- /**
- * Handle a HEAD request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doHead(HttpExchange exchange) throws IOException {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, -1);
- }
- /**
- * Handle an OPTIONS request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doOptions(HttpExchange exchange) throws IOException {
- Set<String> methods = new TreeSet<>();
- Set<String> corsMethods = new TreeSet<>();
- for (Method method : getClass().getDeclaredMethods()) {
- switch (method.getName()) {
- case "doGet":
- methods.add("GET");
- corsMethods.add("GET");
- break;
- case "doPost":
- methods.add("POST");
- break;
- case "doHead":
- methods.add("HEAD");
- break;
- case "doTrace":
- methods.add("TRACE");
- break;
- case "doPut":
- methods.add("PUT");
- break;
- case "doDelete":
- methods.add("DELETE");
- break;
- default:
- break;
- }
- }
- if (!methods.isEmpty()) {
- exchange.getResponseHeaders().set("Allow", String.join(", ", methods));
- }
- if (!corsMethods.isEmpty()) {
- exchange.getResponseHeaders().set("Access-Control-Allow-Methods", String.join(", ", corsMethods));
- }
- if (methods.isEmpty() && corsMethods.isEmpty()) {
- // ... nothing implemented?
- exchange.sendResponseHeaders(TinyHttpStatus.SC_INTERNAL, 0);
- } else {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_NO_CONTENT, -1);
- }
- }
- /**
- * Handle a TRACE request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doTrace(HttpExchange exchange) throws IOException {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, 0);
- }
- /**
- * Handle a PUT request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doPut(HttpExchange exchange) throws IOException {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, 0);
- }
- /**
- * Handle a DELETE request.
- *
- * @param exchange The HTTP exchange.
- * @throws IOException If failed to handle the request.
- */
- protected void doDelete(HttpExchange exchange) throws IOException {
- exchange.sendResponseHeaders(TinyHttpStatus.SC_METHOD_NOT_ALLOWED, 0);
- }
- }