Skip to content

Commit

Permalink
Switch to new httpserver module by grob
Browse files Browse the repository at this point in the history
  • Loading branch information
botic committed Jul 18, 2019
2 parents 449d838 + df40b1f commit 3bea8a2
Show file tree
Hide file tree
Showing 14 changed files with 1,054 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/httpserver-app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var response = require("ringo/jsgi/response");

module.exports = function(req) {
return response.html("Hello World!");
};
34 changes: 34 additions & 0 deletions examples/httpserver-default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
var {HttpServer} = require("../lib/main");

var httpServer = new HttpServer();
httpServer.enableSessions({
"name": "myapp"
});

// init the application context
var appContext = httpServer.serveApplication("/", module.resolve("./app"), {
"sessions": true
});
// and add a websocket to it
appContext.addWebSocket("/events", function() {});

// initialize static file serving
var staticContext = httpServer.serveStatic("/static", module.resolve("./"), {
"allowDirectoryListing": true
});

// http listener
httpServer.createHttpListener({
"port": 8080
});

// https listener
httpServer.createHttpsListener({
"port": 8443,
"keyStore": module.resolve("./keystore"),
"keyStorePassword": "secret",
"keyManagerPassword": "secret"
});

// start
httpServer.jetty.start();
30 changes: 30 additions & 0 deletions examples/httpserver-fluent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var httpServer = require("../lib/main");
var builder = httpServer.build()
// enable sessions with a custom node name
.enableSessions({
"name": "test1"
})
// serve application
.serveApplication("/", module.resolve("./app"), {
"sessions": true
})
// add websocket - this must be called after serveApplication
// as it operates on the current context of the builder
.addWebSocket("/websocket", function() {})
// static file serving
.serveStatic("/static", module.resolve("./"), {
"allowDirectoryListing": true
})
// http listener
.http({
"port": 8080
})
// https listener
.https({
"port": 8443,
"keyStore": module.resolve("./keystore"),
"keyStorePassword": "secret",
"keyManagerPassword": "secret"
})
// start up the server
.start();
10 changes: 10 additions & 0 deletions examples/httpserver-jettyxml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
var httpServer = require("../lib/main");
var builder = httpServer.build("config/jetty.xml")
// serve application
.serveApplication("/", module.resolve("./app"))
// static file serving
.serveStatic("/static", module.resolve("./"), {
"allowDirectoryListing": true
})
// start up the server
.start();
Binary file added examples/keystore
Binary file not shown.
76 changes: 76 additions & 0 deletions modules/ringo/httpserver/builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const HttpServer = require("./httpserver");

const HttpServerBuilder = module.exports = function HttpServerBuilder(options) {
if (!(this instanceof HttpServerBuilder)) {
return new HttpServerBuilder(options);
}
Object.defineProperties(this, {
"server": {
"value": new HttpServer(options)
},
"currentContext": {
"value": null,
"writable": true
}
});
return this;
};

HttpServerBuilder.prototype.toString = function() {
return "[HttpServerBuilder]";
};

HttpServerBuilder.prototype.configure = function(xmlPath) {
this.server.configure(xmlPath);
return this;
};

HttpServerBuilder.prototype.serveApplication = function(mountpoint, app, options) {
this.currentContext = this.server.serveApplication(mountpoint, app, options);
return this;
};

HttpServerBuilder.prototype.serveStatic = function(mountpoint, directory, options) {
this.currentContext = this.server.serveStatic(mountpoint, directory, options);
return this;
};

HttpServerBuilder.prototype.http = function(options) {
this.server.createHttpListener(options);
return this;
};

HttpServerBuilder.prototype.https = function(options) {
this.server.createHttpsListener(options);
return this;
};

HttpServerBuilder.prototype.enableSessions = function(options) {
this.server.enableSessions(options);
return this;
};

HttpServerBuilder.prototype.enableConnectionStatistics = function() {
this.server.enableConnectionStatistics();
return this;
};

HttpServerBuilder.prototype.start = function() {
this.server.start();
return this;
};

HttpServerBuilder.prototype.addWebSocket = function(path, onConnect, onCreate, initParams) {
this.currentContext.addWebSocket(path, onConnect, onCreate, initParams);
return this;
};

HttpServerBuilder.prototype.addEventSource = function(path, onConnect, initParams) {
this.currentContext.addEventSource(path, onConnect, initParams);
return this;
};

HttpServerBuilder.prototype.addFilter = function(path, filter, initParams) {
this.currentContext.addFilter(path, filter, initParams);
return this;
};
73 changes: 73 additions & 0 deletions modules/ringo/httpserver/context/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const log = require("ringo/logging").getLogger(module.id);
const Context = require("./context");
const {JsgiServlet} = org.ringojs.jsgi;
const {WebSocketServlet, WebSocketCreator} = org.eclipse.jetty.websocket.servlet;
const {EventSourceServlet} = org.eclipse.jetty.servlets;
const EventSource = require("../eventsource");
const WebSocket = require("../websocket");

const ApplicationContext = module.exports = function ApplicationContext() {
Context.apply(this, arguments);
return this;
};

ApplicationContext.prototype = Object.create(Context.prototype);
ApplicationContext.prototype.constructor = ApplicationContext;

ApplicationContext.prototype.serve = function(app, engine) {
log.info("Adding JSGI application {} -> {}",
this.contextHandler.getContextPath(), app);
engine = engine || require("ringo/engine").getRhinoEngine();
let servlet = null;
const params = {};
if (typeof(app) === "string") {
params["app-module"] = app;
servlet = new JsgiServlet(engine);
} else if (typeof(app) === "function") {
servlet = new JsgiServlet(engine, app);
} else {
throw new Error("Application must be either a function or the path " +
"to a module exporting a function");
}
return this.addServlet("/*", servlet, params);
};

ApplicationContext.prototype.addWebSocket = function(path, onConnect, onCreate, initParams) {
log.info("Starting websocket support");

const webSocketCreator = new WebSocketCreator({
"createWebSocket": function(request, response) {
if (typeof(onCreate) === "function" && onCreate(request, response) !== true) {
return null;
}
const socket = new WebSocket();
socket.addListener("connect", function(session) {
socket.session = session;
if (typeof onConnect === "function") {
onConnect(socket, session);
}
});

return socket.impl;
}
});

this.addServlet(path, new WebSocketServlet({
"configure": function(factory) {
factory.setCreator(webSocketCreator);
}
}), initParams);
};

ApplicationContext.prototype.addEventSource = function(path, onconnect, initParams) {
log.info("Starting eventsource support");
this.addServlet(path, new EventSourceServlet({
"newEventSource": function(request) {
const socket = new EventSource();
if (typeof onconnect === "function") {
onconnect(socket, request);
}
return socket.impl;
}
}), initParams);
};
85 changes: 85 additions & 0 deletions modules/ringo/httpserver/context/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const log = require("ringo/logging").getLogger(module.id);
const {ServletContextHandler, ServletHolder, FilterHolder} = org.eclipse.jetty.servlet;
const {StatisticsHandler} = org.eclipse.jetty.server.handler;
const {EnumSet} = java.util;
const {DispatcherType} = javax.servlet;

const Context = module.exports = function Context(parentContainer, mountpoint, options) {
let statisticsHandler = null;
if (options.statistics === true) {
// add statistics handler and use it as parent container for
// the context handler created below
statisticsHandler = new StatisticsHandler();
parentContainer.addHandler(statisticsHandler);
parentContainer = statisticsHandler;
}
const contextHandler = new ServletContextHandler(parentContainer, mountpoint,
options.sessions, options.security);
if (options.virtualHosts) {
contextHandler.setVirtualHosts(Array.isArray(options.virtualHosts) ?
options.virtualHosts : [String(options.virtualHosts)]);
}
const sessionHandler = contextHandler.getSessionHandler();
if (sessionHandler !== null) {
if (Number.isInteger(options.sessionsMaxInactiveInterval)) {
sessionHandler.setMaxInactiveInterval(options.sessionsMaxInactiveInterval);
}
const sessionCookieConfig = sessionHandler.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(options.httpOnlyCookies);
sessionCookieConfig.setSecure(options.secureCookies);
if (typeof(options.cookieName) === "string") {
sessionCookieConfig.setName(options.cookieName);
}
sessionCookieConfig.setDomain(options.cookieDomain);
sessionCookieConfig.setPath(options.cookiePath);
sessionCookieConfig.setMaxAge(options.cookieMaxAge);
}

Object.defineProperties(this, {
"statisticsHandler": {
"value": statisticsHandler,
"enumerable": true
},
"contextHandler": {
"value": contextHandler,
"enumerable": true
}
});

return this;
};

Context.prototype.getKey = function() {
const mountpoint = this.contextHandler.getContextPath();
const virtualHosts = this.contextHandler.getVirtualHosts();
if (virtualHosts !== null && virtualHosts.length > 0) {
return String(virtualHosts) + mountpoint;
}
return mountpoint;
};

Context.prototype.addServlet = function(path, servlet, initParams) {
log.debug("Adding servlet {} -> {}", path, "->", servlet);
const servletHolder = new ServletHolder(servlet);
if (initParams != null && initParams.constructor === Object) {
for each (let [key, value] in Iterator(initParams)) {
servletHolder.setInitParameter(key, value);
}
}
this.contextHandler.addServlet(servletHolder, path);
return servletHolder;
};

Context.prototype.addFilter = function(path, filter, initParams) {
log.debug("Adding filter {} -> {}", path, "->", filter);
const filterHolder = new FilterHolder(filter);
filterHolder.setName(filter.getClass().getName());
if (initParams != null && initParams.constructor === Object) {
for each (let [key, value] in Iterator(initParams)) {
filterHolder.setInitParameter(key, value);
}
}
this.contextHandler.addFilter(filterHolder, path,
EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC));
return filterHolder;
};
20 changes: 20 additions & 0 deletions modules/ringo/httpserver/context/static.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const log = require("ringo/logging").getLogger(module.id);
const Context = require("./context");
const {DefaultServlet} = org.eclipse.jetty.servlet;

const StaticContext = module.exports = function StaticContext() {
Context.apply(this, arguments);
return this;
};

StaticContext.prototype = Object.create(Context.prototype);
StaticContext.prototype.constructor = StaticContext;


StaticContext.prototype.serve = function(directory, initParameters) {
log.debug("Adding static handler {} -> {}",
this.contextHandler.getContextPath(), directory);
const repo = getRepository(directory);
this.contextHandler.setResourceBase(repo.exists() ? repo.getPath() : directory);
return this.addServlet("/*", DefaultServlet, initParameters);
};
Loading

0 comments on commit 3bea8a2

Please sign in to comment.