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

com.athaydes.rawhttp.reqinedit.js.JsEnvironment Maven / Gradle / Ivy

There is a newer version: 0.5.0
Show newest version
package com.athaydes.rawhttp.reqinedit.js;

import com.athaydes.rawhttp.reqinedit.HttpEnvironment;
import com.athaydes.rawhttp.reqinedit.HttpTestsReporter;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import rawhttp.core.EagerHttpResponse;
import rawhttp.core.RawHttpResponse;
import rawhttp.core.body.EagerBodyReader;

import javax.annotation.Nullable;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * The default, JavaScript-based {@link HttpEnvironment} used by {@link com.athaydes.rawhttp.reqinedit.ReqInEditUnit}
 * to evaluate HTTP files.
 * 

* This implementation is based on the Java Nashorn engine in an effort to keep compatibility with the JS engine * used in IntelliJ to run HTTP files. *

* Future implementations of {@link HttpEnvironment} may be based on more modern JS engines, such as GraalVM, * which may allow broad compatibility with JS libraries and tools. *

* For help writing Nashorn-based JS, please see the * Nashorn Tutorial. */ public final class JsEnvironment implements HttpEnvironment { private final NashornScriptEngine jsEngine; @Nullable private final File projectDir; /** * Load the environment with the given name. * * @param httpFile the http file that requires an environment. * @param name of environment * @return the environment */ public static JsEnvironment loadEnvironment(@Nullable File httpFile, @Nullable String name) { return new JsEnvironment(httpFile == null ? null : httpFile.getParentFile(), name); } public JsEnvironment() { this(null, null); } public JsEnvironment(@Nullable File projectDir, @Nullable String environmentName) { this.projectDir = projectDir; List environments = environmentName == null ? Collections.emptyList() : JsLoader.getJsObjects(projectDir); jsEngine = (NashornScriptEngine) new ScriptEngineManager().getEngineByName("nashorn"); StringBuilder builder = new StringBuilder(); loadLibraryInto(builder, "Mustache", "/META-INF/resources/webjars/mustache/3.1.0/mustache.js"); readResource("response_handler.js", builder); try { jsEngine.eval(builder.toString()); } catch (ScriptException e) { throw new RuntimeException(e); } if (!environments.isEmpty()) { invoke("__loadEnvironment__", environmentName, environments.get(0), environments.get(1)); } } @Override public Path resolvePath(String path) { return projectDir == null || path.startsWith("/") ? Paths.get(path) : Paths.get(projectDir.getAbsolutePath(), path); } @Override public String renderTemplate(String line) { return invoke("__mustacheRender__", line).toString(); } Object eval(String script) throws ScriptException { return jsEngine.eval(script); } @Override public boolean runResponseHandler(String responseHandler, RawHttpResponse response, HttpTestsReporter testsReporter) throws IOException, ScriptException { setResponse(response.eagerly()); eval(responseHandler); return runAllTests(testsReporter); } void setResponse(EagerHttpResponse response) { Map contentType = contentTypeObject(response.getHeaders().getFirst("Content-Type").orElse("")); invoke("__setResponse__", response.getStatusCode(), response.getHeaders(), contentType, bodyObject(contentType, response.getBody().orElse(null))); } boolean runAllTests(HttpTestsReporter reporter) { return (boolean) invoke("__runAllTests__", reporter); } private Object invoke(String name, Object... args) { try { return jsEngine.invokeFunction(name, args); } catch (ScriptException | NoSuchMethodException e) { throw new RuntimeException(e); } } private static void loadLibraryInto(StringBuilder builder, String name, String path) { builder.append("var exports = {};var module = {};\n"); readResource(path, builder); builder.append("\nvar ").append(name).append(" = Object.keys(exports).length > 0 ? exports : module.exports;" + " exports = {}; module = {};\n"); } private static void readResource(String path, StringBuilder builder) { try (InputStream s = JsEnvironment.class.getResourceAsStream(path)) { BufferedReader reader = new BufferedReader(new InputStreamReader(s, StandardCharsets.UTF_8)); String line; while ((line = reader.readLine()) != null) { builder.append(line); builder.append('\n'); } } catch (IOException e) { throw new RuntimeException(e); } } private static Map contentTypeObject(String contentType) { Map object = new HashMap<>(2); object.put("mimeType", contentType); if (!contentType.isEmpty()) { String[] components = contentType.split(";"); if (components.length > 1) { object.put("mimeType", components[0]); for (int i = 1; i < components.length; i++) { String[] parts = components[i].split("="); if (parts.length == 2) { String attrName = parts[0].trim(); if (attrName.equals("charset")) { object.put("charset", parts[1].trim()); break; } } } } } return object; } private Callable bodyObject(Map contentType, @Nullable EagerBodyReader body) { if (body == null) { return () -> ""; } return () -> body.decodeBodyToString(Charset.forName(contentType.getOrDefault("charset", "UTF-8"))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy