Webserver
This commit is contained in:
parent
36f2821524
commit
a658bc945d
Binary file not shown.
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.ME1312.SubServers</groupId>
|
||||
<artifactId>SubServers.Web</artifactId>
|
||||
<version>-PLACEHOLDER</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>me1312-repo</id>
|
||||
<url>https://dev.me1312.net/maven</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId> <!--suppress MavenPackageUpdate-->
|
||||
<version>1.18</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md_5</groupId>
|
||||
<artifactId>bungeecord-internal</artifactId>
|
||||
<version>1.8-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ME1312.SubServers</groupId>
|
||||
<artifactId>SubServers.Bungee.Common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ME1312.SubServers</groupId>
|
||||
<artifactId>SubServers.Bungee</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>9.4.3.v20170317</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>9.4.3.v20170317</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<directory>../out/compile/target/SubServers.Web</directory>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<configuration>
|
||||
<source>1.7</source> <!-- Source level 1.7 required by com.intellij.forms_rt -->
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>ideauidesigner-maven-plugin</artifactId>
|
||||
<version>1.0-beta-1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>javac2</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<debug>true</debug>
|
||||
<failOnError>true</failOnError>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<mkdir dir="${project.build.directory}" />
|
||||
<copy file="${basedir}/../LICENSE" todir="${project.build.directory}/classes" />
|
||||
</tasks>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-5</version>
|
||||
<configuration>
|
||||
<finalName>SubServers.Console</finalName>
|
||||
<outputDirectory>../Artifacts/Plugins</outputDirectory>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,4 @@
|
|||
name: SubServers-Web
|
||||
main: net.ME1312.SubServers.Web.ConsolePlugin
|
||||
version: 2.18a
|
||||
author: ME1312
|
Binary file not shown.
|
@ -0,0 +1,86 @@
|
|||
package net.ME1312.SubServers.Web;
|
||||
|
||||
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
|
||||
import net.ME1312.SubServers.Bungee.Event.SubCreateEvent;
|
||||
import net.ME1312.SubServers.Bungee.Event.SubSendCommandEvent;
|
||||
import net.ME1312.SubServers.Bungee.Event.SubStartEvent;
|
||||
import net.ME1312.SubServers.Bungee.Host.Host;
|
||||
import net.ME1312.SubServers.Bungee.Host.RemotePlayer;
|
||||
import net.ME1312.SubServers.Bungee.Host.SubCreator;
|
||||
import net.ME1312.SubServers.Bungee.Host.SubServer;
|
||||
import net.ME1312.SubServers.Bungee.Library.Metrics;
|
||||
import net.ME1312.SubServers.Bungee.SubAPI;
|
||||
import net.ME1312.SubServers.Bungee.SubProxy;
|
||||
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public final class ConsolePlugin extends Plugin implements Listener {
|
||||
public YAMLConfig config;
|
||||
private JettyServer jettyServer;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
reload();
|
||||
|
||||
new Metrics(this, 3853).addPlatformCharts();
|
||||
|
||||
jettyServer = new JettyServer();
|
||||
try {
|
||||
jettyServer.start();
|
||||
} catch (Exception e) {
|
||||
getLogger().log(Level.SEVERE, "An error occurred when enabling the webserver, Plugin disabling...", e);
|
||||
this.onDisable();
|
||||
getProxy().getPluginManager().unregisterListeners(this);
|
||||
getProxy().getPluginManager().unregisterCommands(this);
|
||||
}
|
||||
|
||||
SubAPI.getInstance().addListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void reload() {
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onServerCreate(SubCreateEvent event) {
|
||||
if (!event.isCancelled()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onServerStart(SubStartEvent event) {
|
||||
if (!event.isCancelled()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
try {
|
||||
jettyServer.server.stop();
|
||||
} catch (Exception e) {
|
||||
getLogger().log(Level.SEVERE, "An error occurred when disabling the plugin", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubProxy getProxy() {
|
||||
return (SubProxy) super.getProxy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package net.ME1312.SubServers.Web;
|
||||
|
||||
import net.ME1312.SubServers.Web.endpoints.BlockingServlet;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
|
||||
public class JettyServer {
|
||||
public Server server;
|
||||
|
||||
public void start() throws Exception {
|
||||
server = new Server();
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
connector.setPort(8090);
|
||||
server.setConnectors(new Connector[] {connector});
|
||||
|
||||
ServletHandler handler = new ServletHandler();
|
||||
server.setHandler(handler);
|
||||
handler.addServletWithMapping(BlockingServlet.class, "/status");
|
||||
server.start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,336 @@
|
|||
package net.ME1312.SubServers.Web.Library;
|
||||
|
||||
import net.ME1312.Galaxi.Library.Container.Container;
|
||||
|
||||
import org.fusesource.jansi.AnsiOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
public class HTMLogger extends AnsiOutputStream {
|
||||
private static final String[] ANSI_COLOR_MAP = new String[]{"000000", "cd0000", "25bc24", "d7d700", "0000c3", "be00be", "00a5dc", "cccccc"};
|
||||
private static final String[] ANSI_BRIGHT_COLOR_MAP = new String[]{"808080", "ff0000", "31e722", "ffff00", "0000ff", "ff00ff", "00c8ff", "ffffff"};
|
||||
private static final byte[] BYTES_NBSP = "\u00A0".getBytes(UTF_8);
|
||||
private static final byte[] BYTES_AMP = "&".getBytes(UTF_8);
|
||||
private static final byte[] BYTES_LT = "<".getBytes(UTF_8);
|
||||
private LinkedList<String> currentAttributes = new LinkedList<String>();
|
||||
private LinkedList<String> queue = new LinkedList<String>();
|
||||
private OutputStream raw;
|
||||
protected boolean ansi = true;
|
||||
protected boolean nbsp = false;
|
||||
private boolean underline = false;
|
||||
private boolean strikethrough = false;
|
||||
|
||||
public static HTMLogger wrap(OutputStream raw) {
|
||||
return wrap(raw, new HTMConstructor<HTMLogger>() {
|
||||
@Override
|
||||
public HTMLogger construct(OutputStream raw, OutputStream wrapped) {
|
||||
return new HTMLogger(raw, wrapped);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T extends HTMLogger> T wrap(final OutputStream raw, HTMConstructor<T> constructor) {
|
||||
final Container<T> html = new Container<T>(null);
|
||||
html.value(constructor.construct(raw, new OutputStream() {
|
||||
private boolean nbsp = false;
|
||||
|
||||
@Override
|
||||
public void write(int data) throws IOException {
|
||||
HTMLogger htm = html.value();
|
||||
if (htm.queue.size() > 0) {
|
||||
LinkedList<String> queue = htm.queue;
|
||||
htm.queue = new LinkedList<>();
|
||||
for (String attr : queue) {
|
||||
htm.write('<' + attr + '>');
|
||||
htm.currentAttributes.addFirst(attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (data == 32) {
|
||||
if (htm.nbsp) {
|
||||
if (nbsp) raw.write(BYTES_NBSP);
|
||||
else raw.write(data);
|
||||
nbsp = !nbsp;
|
||||
} else raw.write(data);
|
||||
} else {
|
||||
nbsp = false;
|
||||
switch(data) {
|
||||
case '&':
|
||||
raw.write(BYTES_AMP);
|
||||
break;
|
||||
case '<':
|
||||
raw.write(BYTES_LT);
|
||||
break;
|
||||
case '\n':
|
||||
htm.closeAttributes();
|
||||
default:
|
||||
raw.write(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
return html.value();
|
||||
}
|
||||
public HTMLogger(final OutputStream raw, OutputStream wrapped) {
|
||||
super(wrapped);
|
||||
this.raw = raw;
|
||||
}
|
||||
public interface HTMConstructor<T extends HTMLogger> {
|
||||
T construct(OutputStream raw, OutputStream wrapped);
|
||||
}
|
||||
|
||||
private void write(String s) throws IOException {
|
||||
raw.write(s.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
private void writeAttribute(String attr) throws IOException {
|
||||
queue.add(attr);
|
||||
}
|
||||
|
||||
public void closeAttribute(String s) throws IOException {
|
||||
|
||||
// Try to remove a tag that doesn't exist yet first
|
||||
String[] queue = this.queue.toArray(new String[0]);
|
||||
for (int i = queue.length; i > 0;) {
|
||||
String attr = queue[--i];
|
||||
if (attr.toLowerCase().startsWith(s.toLowerCase())) {
|
||||
this.queue.removeLastOccurrence(attr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Close a tag that we've already written
|
||||
LinkedList<String> closedAttributes = new LinkedList<String>();
|
||||
LinkedList<String> currentAttributes = new LinkedList<String>(this.currentAttributes);
|
||||
LinkedList<String> unclosedAttributes = new LinkedList<String>();
|
||||
|
||||
for (String attr : currentAttributes) {
|
||||
if (attr.toLowerCase().startsWith(s.toLowerCase())) {
|
||||
for (String a : unclosedAttributes) {
|
||||
closedAttributes.add(a);
|
||||
this.currentAttributes.removeFirst();
|
||||
write("</" + a.split(" ", 2)[0] + '>');
|
||||
}
|
||||
unclosedAttributes.clear();
|
||||
this.currentAttributes.removeFirst();
|
||||
write("</" + attr.split(" ", 2)[0] + '>');
|
||||
break;
|
||||
} else {
|
||||
unclosedAttributes.add(attr);
|
||||
}
|
||||
}
|
||||
|
||||
// Queue unrelated tags to be re-opened
|
||||
for (String attr : closedAttributes) {
|
||||
this.queue.addFirst(attr);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeAttributes() throws IOException {
|
||||
queue.clear();
|
||||
|
||||
for (String attr : currentAttributes) {
|
||||
write("</" + attr.split(" ", 2)[0] + ">");
|
||||
}
|
||||
|
||||
underline = false;
|
||||
strikethrough = false;
|
||||
currentAttributes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processDeleteLine(int amount) throws IOException {
|
||||
super.processDeleteLine(amount);
|
||||
}
|
||||
|
||||
private void renderTextDecoration() throws IOException {
|
||||
String dec = "";
|
||||
if (underline) dec += " underline";
|
||||
if (strikethrough) dec += " line-through";
|
||||
|
||||
closeAttribute("span style=\"text-decoration:");
|
||||
if (dec.length() != 0) writeAttribute("span style=\"text-decoration:" + dec.substring(1) + "\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetAttribute(int attribute) throws IOException {
|
||||
if (ansi) switch(attribute) {
|
||||
case 1:
|
||||
closeAttribute("b");
|
||||
writeAttribute("b");
|
||||
break;
|
||||
case 3:
|
||||
closeAttribute("i");
|
||||
writeAttribute("i");
|
||||
break;
|
||||
case 4:
|
||||
underline = true;
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 9:
|
||||
strikethrough = true;
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 22:
|
||||
closeAttribute("b");
|
||||
break;
|
||||
case 23:
|
||||
closeAttribute("i");
|
||||
break;
|
||||
case 24:
|
||||
underline = false;
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 29:
|
||||
strikethrough = false;
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 73:
|
||||
closeAttribute("su");
|
||||
writeAttribute("sup");
|
||||
break;
|
||||
case 74:
|
||||
closeAttribute("su");
|
||||
writeAttribute("sub");
|
||||
break;
|
||||
case 75:
|
||||
closeAttribute("su");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processUnknownOperatingSystemCommand(int label, String arg) {
|
||||
try {
|
||||
if (ansi && label == 8) {
|
||||
closeAttribute("a");
|
||||
String[] args = arg.split(";", 3);
|
||||
if (args.length > 1 && args[1].length() > 0 && allowHyperlink(args[1])) {
|
||||
writeAttribute("a href=\"" + args[1].replace("&", "&").replace("<", "<").replace("\"", """) + "\" target=\"_blank\"");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
protected boolean allowHyperlink(String link) {
|
||||
if (link.toLowerCase(Locale.ENGLISH).startsWith("mailto:execute@galaxi.engine")) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processAttributeRest() throws IOException {
|
||||
closeAttributes();
|
||||
}
|
||||
|
||||
private String parse256(int color) throws IOException {
|
||||
if (color < 8) {
|
||||
return ANSI_COLOR_MAP[color];
|
||||
} else if (color < 16) {
|
||||
return ANSI_BRIGHT_COLOR_MAP[color - 8];
|
||||
} else if (color < 232) {
|
||||
float x = color - 16;
|
||||
int r = (int) ((x / 36f) * 51);
|
||||
x = (x % 36f) ;
|
||||
int g = (int) ((x / 6f) * 51);
|
||||
int b = (int) ((x % 6f) * 51);
|
||||
return ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16);
|
||||
} else if (color < 256) {
|
||||
int gray = (int) (10.2f * (color - 231));
|
||||
return ((gray >= 16)?"":"0") + Integer.toString(gray, 16) + ((gray >= 16)?"":"0") + Integer.toString(gray, 16) + ((gray >= 16)?"":"0") + Integer.toString(gray, 16);
|
||||
} else {
|
||||
throw new IOException("Invalid 8 Bit Color: " + color);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processDefaultTextColor() throws IOException {
|
||||
closeAttribute("span style=\"color:");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetForegroundColor(int color) throws IOException {
|
||||
processSetForegroundColor(color, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetForegroundColor(int color, boolean bright) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultTextColor();
|
||||
writeAttribute("span style=\"color:#" + ((!bright)?ANSI_COLOR_MAP:ANSI_BRIGHT_COLOR_MAP)[color] + "\"");
|
||||
renderTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetForegroundColorExt(int index) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultTextColor();
|
||||
writeAttribute("span style=\"color:#" + parse256(index) + "\"");
|
||||
renderTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetForegroundColorExt(int r, int g, int b) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultTextColor();
|
||||
writeAttribute("span style=\"color:#" + ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16) + "\"");
|
||||
renderTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processDefaultBackgroundColor() throws IOException {
|
||||
closeAttribute("span style=\"background-color:");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetBackgroundColor(int color) throws IOException {
|
||||
processSetBackgroundColor(color, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetBackgroundColor(int color, boolean bright) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultBackgroundColor();
|
||||
writeAttribute("span style=\"background-color:#" + ((!bright)?ANSI_COLOR_MAP:ANSI_BRIGHT_COLOR_MAP)[color] + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetBackgroundColorExt(int index) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultBackgroundColor();
|
||||
writeAttribute("span style=\"background-color:#" + parse256(index) + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSetBackgroundColorExt(int r, int g, int b) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultBackgroundColor();
|
||||
writeAttribute("span style=\"background-color:#" + ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16) + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
super.flush();
|
||||
raw.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
closeAttributes();
|
||||
super.close();
|
||||
raw.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package net.ME1312.SubServers.Web.endpoints;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class BlockingServlet extends HttpServlet {
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
response.setContentType("application/json");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().println("{ \"status\": \"ok\"}");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue