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

io.inversion.EngineServlet Maven / Gradle / Ivy

/*
 * Copyright (c) 2015-2018 Rocket Partners, LLC
 * https://github.com/inversion-api
 *
 * 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 io.inversion;

import io.inversion.json.JSNode;
import io.inversion.utils.StreamBuffer;
import io.inversion.utils.Utils;
import io.inversion.utils.ListMap;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;


public class EngineServlet extends HttpServlet {
    Engine engine = null;//new Engine();

    public static String readBody(HttpServletRequest request) throws ApiException {
        if (request == null)
            return null;

        StringBuilder  stringBuilder  = new StringBuilder();
        BufferedReader bufferedReader = null;

        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                if ("gzip".equalsIgnoreCase(request.getHeader("Content-Encoding")))
                    inputStream = new GZIPInputStream(inputStream, 1024);
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int    bytesRead;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            }
        } catch (Exception ex) {
            throw ApiException.new400BadRequest(ex, "Unable to read request body");
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ex) {
                    //throw ex;
                }
            }
        }

        return stringBuilder.toString();
    }

    public void destroy() {
        engine.shutdown();
    }

    public void init(ServletConfig config) {
        engine.startup();
    }

    public Engine getEngine() {
        return engine;
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    @Override
    public void service(HttpServletRequest httpReq, HttpServletResponse httpResp) throws ServletException, IOException {
        EngineServletLocal.set(httpReq, httpResp);

        Response res;
        Request  req;

        try {
            String method = httpReq.getMethod();
            String urlstr = httpReq.getRequestURL().toString();

            if (!urlstr.endsWith("/"))
                urlstr = urlstr + "/";

            String query = httpReq.getQueryString();
            if (!Utils.empty(query)) {
                urlstr += "?" + query;
            }

            String lower = urlstr;
            if (lower.equals("http://localhost")
                    || lower.startsWith("http://localhost/")
                    || lower.startsWith("http://localhost:")
                    || lower.equals("https://localhost")
                    || lower.startsWith("https://localhost/")
                    || lower.startsWith("https://localhost:")
            ) {

                urlstr = Pattern.compile("localhost", Pattern.CASE_INSENSITIVE).matcher(urlstr).replaceFirst("127.0.0.1");
                httpResp.sendRedirect(urlstr);
                return;
            }


            ListMap headers    = new ListMap<>();
            Enumeration    headerEnum = httpReq.getHeaderNames();
            while (headerEnum.hasMoreElements()) {
                String      key    = headerEnum.nextElement();
                Enumeration values = httpReq.getHeaders(key);
                while (values.hasMoreElements()) {
                    String val = (String) values.nextElement();
                    headers.put(key, val);
                }
            }

            Map params       = new HashMap<>();
            Enumeration paramsEnumer = httpReq.getParameterNames();
            while (paramsEnumer.hasMoreElements()) {
                String   key    = paramsEnumer.nextElement();
                String[] values = httpReq.getParameterValues(key);
                String   value  = values == null ? null : (values.length == 1 ? values[0] : Utils.implode(",", values));
                params.put(key, value);
            }

            String body = readBody(httpReq);

            if (body != null && body.startsWith("--") && body.indexOf("Content-Disposition") > 0) {
                throw ApiException.new400BadRequest("Received invalid multipart content.");
            }


            req = new Request(method, urlstr, body, params, headers);
            req.withRemoteAddr(httpReq.getRemoteAddr());

            req.withUploader(() -> {
                try {
                    List uploads = new ArrayList<>();
                    for (Part part : httpReq.getParts()) {
                        String      partName    = part.getName();
                        String      fileName    = part.getSubmittedFileName();
                        InputStream inputStream = part.getInputStream();
                        long        fileSize    = part.getSize();
                        String      fileType    = part.getContentType();

                        //application/octet-stream

                        if (fileName != null && inputStream != null) {
                            uploads.add(new Upload(partName, fileName, fileSize, fileType, inputStream));
                        }
                    }
                    return uploads;
                } catch (Exception ex) {
                    Utils.rethrow(ex);
                }
                return null;
            });

            res = new Response();
            engine.service(req, res);
            writeResponse(req, res, httpResp);
        } catch (Throwable ex) {
            JSNode       json  = Engine.buildErrorJson(ex);
            OutputStream out   = httpResp.getOutputStream();
            byte[]       bytes = json.toString().getBytes(StandardCharsets.UTF_8);
            out.write(bytes);
            out.flush();
            out.close();
        }
    }

    void writeResponse(Request req, Response res, HttpServletResponse http) throws Exception {

        http.setStatus(res.getStatusCode());
        OutputStream out = http.getOutputStream();

        ListMap headers = res.getHeaders();
        headers.keySet().forEach(key -> http.setHeader(key, Utils.implode(",", res.getHeaders().get(key))));

        if (req.isMethod("OPTIONS")) {
            //
        } else {
            String contentType = res.getContentType();
            http.setContentType(contentType);

            StreamBuffer buffer = res.getBody();
            if (buffer != null) {
                http.setContentLength(buffer.getLength());
                Utils.pipe(buffer.getInputStream(), out, true, false);
            }
        }
        out.flush();
        out.close();
    }

    static class EngineServletLocal {
        static final ThreadLocal  request  = new ThreadLocal();
        static final ThreadLocal response = new ThreadLocal();

        public static void set(HttpServletRequest req, HttpServletResponse res) {
            request.set(req);
            response.set(res);
        }

        public static HttpServletRequest getRequest() {
            return request.get();
        }

        public static void setRequest(HttpServletRequest req) {
            request.set(req);
        }

        public static HttpServletResponse getResponse() {
            return response.get();
        }

        public static void setResponse(HttpServletResponse res) {
            response.set(res);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy