fixes and support for h2c
This commit is contained in:
+16
-21
@@ -17,15 +17,24 @@ application{
|
|||||||
mainClass=(group+'.'+name+'.JettyApp')
|
mainClass=(group+'.'+name+'.JettyApp')
|
||||||
}
|
}
|
||||||
java{
|
java{
|
||||||
sourceCompatibility = 1.8
|
// make our library a bit more compatible (jetty forced 11 else it would have been 1.8)
|
||||||
targetCompatibility = 1.8
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
// print some info for orientation
|
dependencies {
|
||||||
//println("group:"+group);
|
def jettyVersion="11.0.18"
|
||||||
//println("name:"+name);
|
implementation "org.eclipse.jetty:jetty-server:${jettyVersion}"
|
||||||
//println("version:"+version);
|
implementation "org.eclipse.jetty.http2:http2-server:${jettyVersion}"
|
||||||
//println("entry:"+mainClassName);
|
implementation "org.slf4j:slf4j-jdk14:2.0.10"
|
||||||
|
//implementation "org.slf4j:slf4j-simple:2.0.10"
|
||||||
|
//implementation 'com.hubspot.jinjava:jinjava:2.5.10'
|
||||||
|
implementation 'com.github.jknack:handlebars:4.3.0'
|
||||||
|
implementation 'com.h2database:h2:2.1.214'
|
||||||
|
implementation 'org.postgresql:postgresql:42.5.0'
|
||||||
|
implementation 'com.zaxxer:HikariCP:5.0.0'
|
||||||
|
testImplementation "junit:junit:4.12"
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
@@ -97,20 +106,6 @@ javadoc {
|
|||||||
links "https://docs.oracle.com/javase/8/docs/api/"
|
links "https://docs.oracle.com/javase/8/docs/api/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
|
||||||
implementation "org.eclipse.jetty:jetty-server:11.0.1"
|
|
||||||
implementation "org.slf4j:slf4j-jdk14:2.0.10"
|
|
||||||
//implementation "org.slf4j:slf4j-simple:2.0.10"
|
|
||||||
//implementation 'com.hubspot.jinjava:jinjava:2.5.10'
|
|
||||||
implementation 'com.github.jknack:handlebars:4.3.0'
|
|
||||||
implementation 'com.h2database:h2:2.1.214'
|
|
||||||
// https://mvnrepository.com/artifact/org.postgresql/postgresql
|
|
||||||
implementation 'org.postgresql:postgresql:42.5.0'
|
|
||||||
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
|
|
||||||
implementation 'com.zaxxer:HikariCP:5.0.0'
|
|
||||||
|
|
||||||
testImplementation "junit:junit:4.12"
|
|
||||||
}
|
|
||||||
test {
|
test {
|
||||||
environment "DB_URL", project.db_url
|
environment "DB_URL", project.db_url
|
||||||
testLogging {
|
testLogging {
|
||||||
|
|||||||
@@ -9,8 +9,13 @@ You may not use this file except in compliance with the License.
|
|||||||
package com.reliancy.jabba;
|
package com.reliancy.jabba;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import com.reliancy.dbo.Terminal;
|
import com.reliancy.dbo.Terminal;
|
||||||
import com.reliancy.jabba.sec.SecurityPolicy;
|
import com.reliancy.jabba.sec.SecurityPolicy;
|
||||||
|
import com.reliancy.jabba.ui.Rendering;
|
||||||
|
import com.reliancy.jabba.ui.Template;
|
||||||
import com.reliancy.util.CodeException;
|
import com.reliancy.util.CodeException;
|
||||||
import com.reliancy.util.ResultCode;
|
import com.reliancy.util.ResultCode;
|
||||||
|
|
||||||
@@ -40,7 +45,8 @@ public abstract class App extends Processor{
|
|||||||
protected Router router=null;
|
protected Router router=null;
|
||||||
protected SecurityPolicy policy=null;
|
protected SecurityPolicy policy=null;
|
||||||
protected Terminal storage=null;
|
protected Terminal storage=null;
|
||||||
|
protected Map<String,AppModule> modules;
|
||||||
|
|
||||||
public App(String id) {
|
public App(String id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
@@ -57,6 +63,71 @@ public abstract class App extends Processor{
|
|||||||
if(first!=null && resp.getStatus()==null) first.process(req, resp);
|
if(first!=null && resp.getStatus()==null) first.process(req, resp);
|
||||||
if(router!=null && resp.getStatus()==null) router.process(req,resp);
|
if(router!=null && resp.getStatus()==null) router.process(req,resp);
|
||||||
}
|
}
|
||||||
|
/** When an error occurs we need properly render exception.
|
||||||
|
* if html is accepted we try to render a valid response with n error within a template so it fits with the app.
|
||||||
|
* for all others we set error status code.
|
||||||
|
* for json,xml and plain we render into a message template for the rest we do nothing.
|
||||||
|
* this method returns true if a response was generated. in overloaded methods
|
||||||
|
* if false is returned we can generate response the status is set to 500 already.
|
||||||
|
* @param req incoming request
|
||||||
|
* @param ex exception state
|
||||||
|
* @param resp response to generate
|
||||||
|
* @return true if handled else it signifies we should do somthing in overloads.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public boolean processError(com.reliancy.jabba.Request req,Throwable ex,com.reliancy.jabba.Response resp) throws IOException{
|
||||||
|
log().error("error:",ex);
|
||||||
|
String accepted_format=req.getHeader("Accept");
|
||||||
|
boolean present=accepted_format!=null;
|
||||||
|
if(present && (
|
||||||
|
accepted_format.contains("/html")
|
||||||
|
|| accepted_format.contains("/xhtml")
|
||||||
|
)){
|
||||||
|
// we have html request
|
||||||
|
resp.setContentType(HTTP.MIME_HTML);
|
||||||
|
Template t=Template.find("/templates/error.hbs");
|
||||||
|
if(t==null){ // no template found
|
||||||
|
resp.setStatus(Response.HTTP_INTERNAL_ERROR);
|
||||||
|
if(ex instanceof IOException) throw ((IOException)ex);
|
||||||
|
else throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
Rendering.begin(t).with(ex).end(resp);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
// for all other cases we first flag it as error
|
||||||
|
resp.setStatus(Response.HTTP_INTERNAL_ERROR);
|
||||||
|
}
|
||||||
|
// next we format a few common and supported messages
|
||||||
|
if(present && accepted_format.contains("/json")){
|
||||||
|
ResponseEncoder enc=resp.getEncoder();
|
||||||
|
if(enc.getErrorFormat()==null){
|
||||||
|
String template="'{'\n\t\"status\":\"error\",\n\t\"title\":\"{0}\",\n\t\"message\":\"{1}\"\n'}'\n";
|
||||||
|
enc.setErrorFormat(template);
|
||||||
|
}
|
||||||
|
enc.writeError(ex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(present && accepted_format.contains("/xml")){
|
||||||
|
ResponseEncoder enc=resp.getEncoder();
|
||||||
|
if(enc.getErrorFormat()==null){
|
||||||
|
String template="<response>\n\t<status>error</status>\n\t<title>{0}</title>\n\t<message>{1}</message>\n</response>\n";
|
||||||
|
enc.setErrorFormat(template);
|
||||||
|
}
|
||||||
|
enc.writeError(ex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(present && accepted_format.contains("text/plain")){
|
||||||
|
ResponseEncoder enc=resp.getEncoder();
|
||||||
|
if(enc.getErrorFormat()==null){
|
||||||
|
String template="status=error\n\ntitle={0}\n\nmessage={1}\n\n";
|
||||||
|
enc.setErrorFormat(template);
|
||||||
|
}
|
||||||
|
enc.writeError(ex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** add one or a chain of processors. */
|
/** add one or a chain of processors. */
|
||||||
public <T extends Processor> T addMiddleWare(T m){
|
public <T extends Processor> T addMiddleWare(T m){
|
||||||
if(m==null) return null;
|
if(m==null) return null;
|
||||||
@@ -183,4 +254,37 @@ public abstract class App extends Processor{
|
|||||||
public Terminal getStorage(){
|
public Terminal getStorage(){
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
/** register module under one or more names.
|
||||||
|
* if no names are provided just calls module to publish itself.
|
||||||
|
* @param module
|
||||||
|
* @param names
|
||||||
|
*/
|
||||||
|
public void publishModule(AppModule module,String...names){
|
||||||
|
if(names.length==0){
|
||||||
|
module.publish(this);
|
||||||
|
}else{
|
||||||
|
if(modules==null) modules=new HashMap<>();
|
||||||
|
for(String nm:names) if(nm!=null) modules.put(nm.toLowerCase(),module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** retracts module under given names.
|
||||||
|
* if no names provided calls on module to retract itself.
|
||||||
|
*/
|
||||||
|
public void retractModule(AppModule module,String...names){
|
||||||
|
if(names.length==0){
|
||||||
|
module.retract(this);
|
||||||
|
// if injected from outside we remove those too
|
||||||
|
if(modules!=null) while(modules.values().remove(module));
|
||||||
|
}else{
|
||||||
|
if(modules==null) return;
|
||||||
|
for(String nm:names){
|
||||||
|
if("*".equals(nm)){ // special case to remove all
|
||||||
|
while(modules.values().remove(module));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
modules.remove(nm.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@ package com.reliancy.jabba;
|
|||||||
*/
|
*/
|
||||||
public interface AppModule {
|
public interface AppModule {
|
||||||
void publish(App app);
|
void publish(App app);
|
||||||
default void retract(App app){};
|
default void retract(App app){
|
||||||
|
app.retractModule(this,"*");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,9 @@ public class ArgsConfig extends Config.Base{
|
|||||||
APP_SETTINGS.set(this, cwd);
|
APP_SETTINGS.set(this, cwd);
|
||||||
}
|
}
|
||||||
// also logging level and format
|
// also logging level and format
|
||||||
|
// System.out.println("LogLog:"+LOG_LEVEL.get(this));
|
||||||
|
// System.out.println("ENV:"+System.getenv("LOG_LEVEL"));
|
||||||
|
// LOG_LEVEL.set(this,"INFO");
|
||||||
Logger root=Log.setup();
|
Logger root=Log.setup();
|
||||||
Log.setLevel(root,LOG_LEVEL.get(this));
|
Log.setLevel(root,LOG_LEVEL.get(this));
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
package com.reliancy.jabba;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.reliancy.jabba.sec.NotAuthentic;
|
|
||||||
import com.reliancy.jabba.sec.Secured;
|
|
||||||
import com.reliancy.jabba.sec.SecurityActor;
|
|
||||||
import com.reliancy.jabba.sec.SecurityPolicy;
|
|
||||||
import com.reliancy.jabba.ui.Feedback;
|
|
||||||
import com.reliancy.jabba.ui.FeedbackLine;
|
|
||||||
import com.reliancy.jabba.ui.Rendering;
|
|
||||||
import com.reliancy.jabba.ui.Template;
|
|
||||||
|
|
||||||
public class DemoEP implements AppModule{
|
|
||||||
@Override
|
|
||||||
public void publish(App app) {
|
|
||||||
app.getRouter().importMethods(this);
|
|
||||||
}
|
|
||||||
@Routed()
|
|
||||||
public String hello(){
|
|
||||||
Map<String, Object> context = new HashMap<>();
|
|
||||||
context.put("name", "Jared");
|
|
||||||
String ret="";
|
|
||||||
try {
|
|
||||||
Template t=Template.find("/templates/login.hbs");
|
|
||||||
System.out.println("Template:"+t);
|
|
||||||
ret = t.render(context).toString();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
//#return "Hello World";
|
|
||||||
}
|
|
||||||
@Routed(
|
|
||||||
path="/helloPlain"
|
|
||||||
)
|
|
||||||
public void hello2(com.reliancy.jabba.Request req,Response resp) throws IOException{
|
|
||||||
resp.getEncoder().writeln("Hi There");
|
|
||||||
}
|
|
||||||
@Routed(
|
|
||||||
path="/hello3/{idd:int}"
|
|
||||||
)
|
|
||||||
public String hello3(int id){
|
|
||||||
return "Hello3:"+id;
|
|
||||||
}
|
|
||||||
@Routed(
|
|
||||||
path="/"
|
|
||||||
)
|
|
||||||
public String home(){
|
|
||||||
StringBuilder buf=new StringBuilder();
|
|
||||||
buf.append("<p>Sample pages:</p>");
|
|
||||||
buf.append("<dd><a href='/helloPlain'>plain</a></dd>");
|
|
||||||
buf.append("<dd><a href='/hello3/5'>parametric</a></dd>");
|
|
||||||
buf.append("<dd><a href='/hello'>templated</a></dd>");
|
|
||||||
buf.append("<dd><a href='/secured'>secured http</a></dd>");
|
|
||||||
buf.append("<dd><a href='/secured_form'>secured form</a></dd>");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
@Routed
|
|
||||||
@Secured
|
|
||||||
public String secured(){
|
|
||||||
return "We are secured";
|
|
||||||
}
|
|
||||||
@Routed
|
|
||||||
@Secured(
|
|
||||||
login_form = "/login"
|
|
||||||
)
|
|
||||||
public String secured_form(){
|
|
||||||
return "We are secured by form";
|
|
||||||
}
|
|
||||||
@Routed
|
|
||||||
public void login(com.reliancy.jabba.Request req,Response resp){
|
|
||||||
//return "login form here";
|
|
||||||
if(req.getVerb().equals("POST")){
|
|
||||||
// here we need to process login and redirect
|
|
||||||
AppSession ass=AppSession.getInstance();
|
|
||||||
try{
|
|
||||||
System.out.println("Post login");
|
|
||||||
String userid=(String)req.getParam("userid",null);
|
|
||||||
String pwd=(String)req.getParam("password",null);
|
|
||||||
System.out.println("SS:"+ass);
|
|
||||||
System.out.println("P:"+userid+"/"+pwd);
|
|
||||||
SecurityPolicy secpol=ass.getApp().getSecurityPolicy();
|
|
||||||
SecurityActor user=secpol.authenticate(userid, pwd);
|
|
||||||
if(user==null) throw new NotAuthentic("invalid credentials");
|
|
||||||
resp.setStatus(Response.HTTP_FOUND_REDIRECT);
|
|
||||||
//String old_url=request.getPath();
|
|
||||||
//old_url=URLEncoder.encode(old_url,StandardCharsets.UTF_8.toString());
|
|
||||||
resp.setHeader("Location","/home");
|
|
||||||
}catch(Exception ex){
|
|
||||||
ass.getApp().log().error("error:",ex);
|
|
||||||
Feedback.get().push(FeedbackLine.error(ex.getLocalizedMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Map<String, Object> context = new HashMap<>();
|
|
||||||
//context.put("app_title", "Jabba Login");
|
|
||||||
//context.put("name", "Jared");
|
|
||||||
//ArrayList<FeedbackLine> events=new ArrayList<>();
|
|
||||||
|
|
||||||
//Feedback.get().push(FeedbackLine.error("Error"));
|
|
||||||
//Feedback.get().push(FeedbackLine.info("Error"));
|
|
||||||
//Feedback.get().push(FeedbackLine.warn("Error"));
|
|
||||||
//context.put("feedback",events);
|
|
||||||
try {
|
|
||||||
resp.setContentType("text/html");
|
|
||||||
Rendering.begin("/templates/login.hbs")
|
|
||||||
//.with("feedback",events)
|
|
||||||
.end(resp);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -140,11 +140,11 @@ public class FileServer extends EndPoint implements AppModule,Resources.PathRewr
|
|||||||
String path=request.getPath();
|
String path=request.getPath();
|
||||||
Logger logger=log();
|
Logger logger=log();
|
||||||
boolean atDebug=logger.isDebugEnabled();
|
boolean atDebug=logger.isDebugEnabled();
|
||||||
if(atDebug) logger.debug("{0}:{1}",verb,path);
|
if(atDebug) logger.debug("{}:{}",verb,path);
|
||||||
for(Bucket bucket:buckets){
|
if(HTTP.VERB_GET.equals(verb)){
|
||||||
String local_path=bucket.asContained(path);
|
for(Bucket bucket:buckets){
|
||||||
if(local_path==null) continue; // this bucket is not accepting
|
String local_path=bucket.asContained(path);
|
||||||
if(HTTP.VERB_GET.equals(verb)){
|
if(local_path==null) continue; // this bucket is not accepting
|
||||||
try(InputStream ins=bucket.openSource(local_path,this)){
|
try(InputStream ins=bucket.openSource(local_path,this)){
|
||||||
if(ins==null) continue; // url did not take
|
if(ins==null) continue; // url did not take
|
||||||
String etag=bucket.signature(local_path);
|
String etag=bucket.signature(local_path);
|
||||||
@@ -166,30 +166,38 @@ public class FileServer extends EndPoint implements AppModule,Resources.PathRewr
|
|||||||
enc.writeStream(ins);
|
enc.writeStream(ins);
|
||||||
return; // we got something
|
return; // we got something
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
// these verbs are not supported
|
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
// these verbs are not supported
|
||||||
}
|
}
|
||||||
response.setStatus(Response.HTTP_NOT_FOUND);
|
response.setStatus(Response.HTTP_NOT_FOUND);
|
||||||
response.getEncoder().writeln("missing file:{0}",path);
|
response.getEncoder().writeln("missing file:"+path);
|
||||||
logger.error("not found:{0}",path);
|
logger.error("not found:{}",path);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Will render a URL resource to response.
|
* Will render a URL resource to response.
|
||||||
* @param f
|
* @param f
|
||||||
* @param response
|
* @param response
|
||||||
*/
|
*/
|
||||||
protected static void writeResource(URL f, Response response) throws IOException{
|
public static boolean sendData(URL f, Response response) throws IOException{
|
||||||
//log().info("writing:"+f);
|
|
||||||
ResponseEncoder enc=response.getEncoder();
|
|
||||||
try(InputStream is=f.openStream()){
|
try(InputStream is=f.openStream()){
|
||||||
String ctype=HTTP.guess_mime(f);
|
if(is==null) return false;
|
||||||
response.setStatus(Response.HTTP_OK);
|
response.setStatus(Response.HTTP_OK);
|
||||||
|
String ctype=HTTP.guess_mime(f);
|
||||||
response.setContentType(ctype);
|
response.setContentType(ctype);
|
||||||
|
ResponseEncoder enc=response.getEncoder();
|
||||||
enc.writeStream(is);
|
enc.writeStream(is);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** adds a route which serves files.
|
public static boolean sendData(InputStream istr, Response response) throws IOException{
|
||||||
|
if(istr==null) return false;
|
||||||
|
ResponseEncoder enc=response.getEncoder();
|
||||||
|
response.setStatus(Response.HTTP_OK);
|
||||||
|
enc.writeStream(istr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/** adds a route which serves files.
|
||||||
* if disk_path is ommited (0 len) or null we use Resources.search_path.
|
* if disk_path is ommited (0 len) or null we use Resources.search_path.
|
||||||
* @param bucket resource holder to add
|
* @param bucket resource holder to add
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ You may not use this file except in compliance with the License.
|
|||||||
package com.reliancy.jabba;
|
package com.reliancy.jabba;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.EventListener;
|
import java.util.EventListener;
|
||||||
|
|
||||||
import com.reliancy.jabba.sec.SecurityPolicy;
|
import com.reliancy.jabba.sec.SecurityPolicy;
|
||||||
@@ -16,11 +17,19 @@ import com.reliancy.jabba.ui.Menu;
|
|||||||
import com.reliancy.jabba.ui.MenuItem;
|
import com.reliancy.jabba.ui.MenuItem;
|
||||||
import com.reliancy.jabba.ui.Rendering;
|
import com.reliancy.jabba.ui.Rendering;
|
||||||
import com.reliancy.jabba.ui.Template;
|
import com.reliancy.jabba.ui.Template;
|
||||||
|
import com.reliancy.rec.JSONEncoder;
|
||||||
|
import com.reliancy.util.CodeException;
|
||||||
import com.reliancy.util.Log;
|
import com.reliancy.util.Log;
|
||||||
import com.reliancy.util.Resources;
|
import com.reliancy.util.Resources;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
|
||||||
|
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
|
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||||
|
import org.eclipse.jetty.server.MultiPartFormDataCompliance;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.server.ServerConnector;
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
@@ -28,10 +37,14 @@ import org.eclipse.jetty.server.ServerConnector;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router is entry point and servlet implementation that dispatches messages to our endpoints.
|
* Router is entry point and servlet implementation that dispatches messages to our endpoints.
|
||||||
* It will launch an embedded jetty server.
|
* It will launch an embedded jetty server.
|
||||||
* It will provide facilities to register endpoints.
|
* It will provide facilities to register endpoints via router.
|
||||||
|
* Mostly new routes are injected via AppModules which publish themselves.
|
||||||
|
* JettyApp installs ForwardCustomizer to react to reverse proxy setups.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class JettyApp extends App implements Handler{
|
public class JettyApp extends App implements Handler{
|
||||||
enum State{
|
enum State{
|
||||||
@@ -52,15 +65,22 @@ public class JettyApp extends App implements Handler{
|
|||||||
jetty.setHandler(this);
|
jetty.setHandler(this);
|
||||||
_state=State.STOPPED;
|
_state=State.STOPPED;
|
||||||
}
|
}
|
||||||
/** implementation of jetty handler interface */
|
|
||||||
public Connector[] getConnectors(){
|
public Connector[] getConnectors(){
|
||||||
if(connectors!=null) return connectors;
|
if(connectors!=null) return connectors;
|
||||||
ServerConnector connector = new ServerConnector(jetty);
|
// Create HTTP Config
|
||||||
connector.setReuseAddress(false);
|
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||||
connector.setPort(8090);
|
// Add support for X-Forwarded headers
|
||||||
connectors=new Connector[] {connector};
|
httpConfig.addCustomizer( new ForwardedRequestCustomizer() );
|
||||||
|
// Create the http connector
|
||||||
|
HttpConnectionFactory http11 = new HttpConnectionFactory( httpConfig );
|
||||||
|
HTTP2ServerConnectionFactory h2c = new HTTP2CServerConnectionFactory(httpConfig);
|
||||||
|
ServerConnector httpConn = new ServerConnector(jetty,http11,h2c);
|
||||||
|
httpConn.setReuseAddress(false);
|
||||||
|
httpConn.setPort(8090);
|
||||||
|
connectors=new Connector[] {httpConn};
|
||||||
return connectors;
|
return connectors;
|
||||||
}
|
}
|
||||||
|
/** implementation of jetty handler interface */
|
||||||
@Override
|
@Override
|
||||||
public Server getServer() {
|
public Server getServer() {
|
||||||
return jetty;
|
return jetty;
|
||||||
@@ -68,12 +88,10 @@ public class JettyApp extends App implements Handler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setServer(Server arg0) {
|
public void setServer(Server arg0) {
|
||||||
System.out.println("setServer..."+jetty+"/"+arg0);
|
|
||||||
jetty=arg0;
|
jetty=arg0;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean addEventListener(EventListener arg0) {
|
public boolean addEventListener(EventListener arg0) {
|
||||||
System.out.println("adding evt listener...");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@@ -160,16 +178,8 @@ public class JettyApp extends App implements Handler{
|
|||||||
try{
|
try{
|
||||||
ss.begin(null, req, resp);
|
ss.begin(null, req, resp);
|
||||||
process(req,resp);
|
process(req,resp);
|
||||||
}catch(IOException ioex){
|
}catch(Exception ioex){
|
||||||
Template t=Template.find("/templates/error.hbs");
|
processError(req,ioex,resp);
|
||||||
if(t==null) throw ioex;
|
|
||||||
Rendering.begin(t).with(ioex).end(resp);
|
|
||||||
log().error("error:",ioex);
|
|
||||||
}catch(RuntimeException rex){
|
|
||||||
Template t=Template.find("/templates/error.hbs");
|
|
||||||
if(t==null) throw rex;
|
|
||||||
Rendering.begin(t).with(rex).end(resp);
|
|
||||||
log().error("error:",rex);
|
|
||||||
}finally{
|
}finally{
|
||||||
baseRequest.setHandled(true);
|
baseRequest.setHandled(true);
|
||||||
ss.end();
|
ss.end();
|
||||||
@@ -246,7 +256,7 @@ public class JettyApp extends App implements Handler{
|
|||||||
app.setSecurityPolicy(secpol);
|
app.setSecurityPolicy(secpol);
|
||||||
// install router
|
// install router
|
||||||
app.setRouter(new Router());
|
app.setRouter(new Router());
|
||||||
DemoEP ep=new DemoEP();
|
StatusMod ep=new StatusMod();
|
||||||
ep.publish(app);
|
ep.publish(app);
|
||||||
// install file sever endpoint
|
// install file sever endpoint
|
||||||
FileServer fs=new FileServer("/static","/public");
|
FileServer fs=new FileServer("/static","/public");
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public abstract class Processor {
|
|||||||
|
|
||||||
public Processor(String id){
|
public Processor(String id){
|
||||||
next=null;
|
next=null;
|
||||||
this.id=id!=null?id:this.getClass().getSimpleName().toLowerCase();
|
this.id=id!=null?id:this.getClass().getSimpleName();
|
||||||
active=true;
|
active=true;
|
||||||
}
|
}
|
||||||
public String getId(){
|
public String getId(){
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
public class Request {
|
public class Request {
|
||||||
final HttpServletRequest http_request;
|
final HttpServletRequest http_request;
|
||||||
final HashMap<String,String> pathParams=new HashMap<>();
|
final HashMap<String,String> pathParams=new HashMap<>();
|
||||||
|
String pathOverride;
|
||||||
public Request(HttpServletRequest http_request) {
|
public Request(HttpServletRequest http_request) {
|
||||||
this.http_request = http_request;
|
this.http_request = http_request;
|
||||||
}
|
}
|
||||||
@@ -25,9 +26,16 @@ public class Request {
|
|||||||
return pathParams;
|
return pathParams;
|
||||||
}
|
}
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return http_request.getPathInfo();
|
if(pathOverride!=null){
|
||||||
|
return pathOverride;
|
||||||
|
}else{
|
||||||
|
return http_request.getPathInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Request setPath(String path){
|
||||||
|
pathOverride=path;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVerb() {
|
public String getVerb() {
|
||||||
return http_request.getMethod();
|
return http_request.getMethod();
|
||||||
}
|
}
|
||||||
@@ -76,6 +84,10 @@ public class Request {
|
|||||||
"HTTP_FORWARDED",
|
"HTTP_FORWARDED",
|
||||||
"HTTP_VIA",
|
"HTTP_VIA",
|
||||||
"REMOTE_ADDR" };
|
"REMOTE_ADDR" };
|
||||||
|
/**
|
||||||
|
* This method will consult several headers to obain ip address.
|
||||||
|
* @return best guess for remote address.
|
||||||
|
*/
|
||||||
public String getRemoteAddress() {
|
public String getRemoteAddress() {
|
||||||
for (String header : HEADERS4IP) {
|
for (String header : HEADERS4IP) {
|
||||||
String ip = getHeader(header);
|
String ip = getHeader(header);
|
||||||
@@ -84,4 +96,27 @@ public class Request {
|
|||||||
}
|
}
|
||||||
return http_request.getRemoteAddr();
|
return http_request.getRemoteAddr();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* will return shema://host:port/context
|
||||||
|
* @return everything preceeding the path.
|
||||||
|
*/
|
||||||
|
public String getMount(){
|
||||||
|
String scheme = http_request.getScheme();
|
||||||
|
String host = http_request.getHeader("Host"); // includes server name and server port
|
||||||
|
if(host==null || host.trim().isEmpty()){
|
||||||
|
// try differenty for host
|
||||||
|
String serverName = http_request.getServerName();
|
||||||
|
int serverPort = http_request.getServerPort();
|
||||||
|
host=serverName+":"+serverPort;
|
||||||
|
}
|
||||||
|
String resultPath = scheme + "://" + host;
|
||||||
|
String contextPath = http_request.getContextPath(); // includes leading forward slash
|
||||||
|
if(contextPath!=null){
|
||||||
|
resultPath+= contextPath;
|
||||||
|
}
|
||||||
|
return resultPath;
|
||||||
|
}
|
||||||
|
public String getProtocol(){
|
||||||
|
return http_request.getProtocol();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public class Response {
|
|||||||
public static final int HTTP_TEMPORARY_REDIRECT=HttpServletResponse.SC_TEMPORARY_REDIRECT;
|
public static final int HTTP_TEMPORARY_REDIRECT=HttpServletResponse.SC_TEMPORARY_REDIRECT;
|
||||||
public static final int HTTP_FOUND_REDIRECT=HttpServletResponse.SC_FOUND;
|
public static final int HTTP_FOUND_REDIRECT=HttpServletResponse.SC_FOUND;
|
||||||
public static final int HTTP_NOT_MODIFIED=HttpServletResponse.SC_NOT_MODIFIED;
|
public static final int HTTP_NOT_MODIFIED=HttpServletResponse.SC_NOT_MODIFIED;
|
||||||
|
public static final int HTTP_INTERNAL_ERROR=HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
final protected HttpServletResponse http_response;
|
final protected HttpServletResponse http_response;
|
||||||
final protected Writer char_response;
|
final protected Writer char_response;
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ import java.text.MessageFormat;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import com.reliancy.rec.JSONEncoder;
|
||||||
|
import com.reliancy.util.CodeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class will replace the Java writer.
|
* This class will replace the Java writer.
|
||||||
* It will have chainable calls. It will inherit lower level calls
|
* It will have chainable calls. It will inherit lower level calls
|
||||||
@@ -35,6 +38,8 @@ public class ResponseEncoder implements Appendable,Closeable{
|
|||||||
protected Writer writer;
|
protected Writer writer;
|
||||||
protected OutputStream out;
|
protected OutputStream out;
|
||||||
protected Charset charSet;
|
protected Charset charSet;
|
||||||
|
protected String errorFmt;
|
||||||
|
|
||||||
public ResponseEncoder(Response r){
|
public ResponseEncoder(Response r){
|
||||||
this(r,StandardCharsets.UTF_8);
|
this(r,StandardCharsets.UTF_8);
|
||||||
//response=r;
|
//response=r;
|
||||||
@@ -118,6 +123,28 @@ public class ResponseEncoder implements Appendable,Closeable{
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public ResponseEncoder setErrorFormat(String fmt){
|
||||||
|
errorFmt=fmt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public String getErrorFormat(){
|
||||||
|
return this.errorFmt;
|
||||||
|
}
|
||||||
|
public ResponseEncoder writeError(Throwable ex) throws IOException{
|
||||||
|
if(errorFmt==null){
|
||||||
|
this.writeString(ex.toString());
|
||||||
|
}else{
|
||||||
|
StringBuilder title=new StringBuilder();
|
||||||
|
StringBuilder detail=new StringBuilder();
|
||||||
|
CodeException.fillUserMessage(ex, detail, title);
|
||||||
|
String body=MessageFormat.format(
|
||||||
|
errorFmt,
|
||||||
|
JSONEncoder.escape(title),
|
||||||
|
JSONEncoder.escape(detail));
|
||||||
|
writeString(body);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public ResponseEncoder writeObject(Object ret) throws IOException{
|
public ResponseEncoder writeObject(Object ret) throws IOException{
|
||||||
if(ret==null) return this;
|
if(ret==null) return this;
|
||||||
Writer wr=getWriter();
|
Writer wr=getWriter();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class Router extends Processor{
|
|||||||
Pattern regex;
|
Pattern regex;
|
||||||
|
|
||||||
public Router() {
|
public Router() {
|
||||||
super("router");
|
super("Router");
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void before(Request request, Response response) throws IOException {
|
public void before(Request request, Response response) throws IOException {
|
||||||
@@ -64,9 +64,28 @@ public class Router extends Processor{
|
|||||||
resp.getEncoder().writeln("could not resolve path:"+path);
|
resp.getEncoder().writeln("could not resolve path:"+path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/** Lookup of endpoints by full routing string.
|
||||||
|
* that includes verb.
|
||||||
|
* @param r routing path
|
||||||
|
* @return endpoint matching path
|
||||||
|
*/
|
||||||
public EndPoint getRoute(String r){
|
public EndPoint getRoute(String r){
|
||||||
return routes.get(r);
|
return routes.get(r);
|
||||||
}
|
}
|
||||||
|
/** Lookup of endpoint by method name or part of it.
|
||||||
|
* matches if endpoint id endswith method_name.
|
||||||
|
* matches case insensitively.
|
||||||
|
* @param method_name ending part of a method
|
||||||
|
* @return matched endpoint
|
||||||
|
*/
|
||||||
|
public EndPoint getRouteByMethod(String method_name){
|
||||||
|
method_name=method_name.toLowerCase();
|
||||||
|
for(EndPoint ep:routes.values()){
|
||||||
|
String nm=ep.getId().toLowerCase();
|
||||||
|
if(nm.endsWith(method_name)) return ep;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public void addRoute(String verb,String path, EndPoint mm) {
|
public void addRoute(String verb,String path, EndPoint mm) {
|
||||||
RouteDetector det=new RouteDetector(verb,path);
|
RouteDetector det=new RouteDetector(verb,path);
|
||||||
detectors.add(det);
|
detectors.add(det);
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.reliancy.jabba;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class StatusMod implements AppModule{
|
||||||
|
@Override
|
||||||
|
public void publish(App app) {
|
||||||
|
app.publishModule(this,getClass().getSimpleName());
|
||||||
|
app.getRouter().importMethods(this);
|
||||||
|
}
|
||||||
|
@Routed(
|
||||||
|
path="/status"
|
||||||
|
)
|
||||||
|
public void status(Request req,Response resp) throws IOException{
|
||||||
|
StringBuilder buf=new StringBuilder();
|
||||||
|
if(buf!=null) throw new IOException("bummer!!!");
|
||||||
|
buf.append("Hi there!!!\n");
|
||||||
|
buf.append("mount:").append(req.getMount()).append("\n");
|
||||||
|
buf.append("path:").append(req.getPath()).append("\n");
|
||||||
|
buf.append("remote:").append(req.getRemoteAddress()).append("\n");
|
||||||
|
buf.append("protocol:").append(req.getProtocol()).append("\n");
|
||||||
|
resp.getEncoder().writeString(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -140,7 +140,7 @@ public class JSONEncoder{
|
|||||||
// we must be consistent so that repeated parse and encode works and not too smart here
|
// we must be consistent so that repeated parse and encode works and not too smart here
|
||||||
// we need to put quotes around unless
|
// we need to put quotes around unless
|
||||||
if (!jsontxt) {
|
if (!jsontxt) {
|
||||||
str = escape(str);
|
str = escape(str).toString();
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
o.append('"');
|
o.append('"');
|
||||||
}
|
}
|
||||||
@@ -247,48 +247,48 @@ public class JSONEncoder{
|
|||||||
* @param str input string
|
* @param str input string
|
||||||
* @return output after encoding special chars
|
* @return output after encoding special chars
|
||||||
*/
|
*/
|
||||||
public static String escape(String str) {
|
public static CharSequence escape(CharSequence str) {
|
||||||
StringBuilder buf = null;
|
StringBuilder buf = null;
|
||||||
for (int i = 0; i < str.length(); i++) {
|
for (int i = 0; i < str.length(); i++) {
|
||||||
char ch = str.charAt(i);
|
char ch = str.charAt(i);
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '"':
|
case '"':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\\"");
|
buf.append("\\\"");
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\\\");
|
buf.append("\\\\");
|
||||||
break;
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\/");
|
buf.append("\\/");
|
||||||
break;
|
break;
|
||||||
case '\b':
|
case '\b':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\b");
|
buf.append("\\b");
|
||||||
break;
|
break;
|
||||||
case '\f':
|
case '\f':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\f");
|
buf.append("\\f");
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\n");
|
buf.append("\\n");
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\r");
|
buf.append("\\r");
|
||||||
break;
|
break;
|
||||||
case '\t':
|
case '\t':
|
||||||
if(buf==null) buf=new StringBuilder(str.substring(0,i));
|
if(buf==null) buf=new StringBuilder(str.subSequence(0,i));
|
||||||
buf.append("\\t");
|
buf.append("\\t");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(buf!=null) buf.append(ch);
|
if(buf!=null) buf.append(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buf!=null?buf.toString():str;
|
return buf!=null?buf:str;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class CodeException extends RuntimeException {
|
|||||||
}
|
}
|
||||||
public static Throwable fillUserMessage(Throwable ex,StringBuilder msg,StringBuilder title) {
|
public static Throwable fillUserMessage(Throwable ex,StringBuilder msg,StringBuilder title) {
|
||||||
Throwable c = ex;
|
Throwable c = ex;
|
||||||
System.out.println(">>>"+c+"/"+c.getCause());
|
//System.out.println(">>>"+c+"/"+c.getCause());
|
||||||
while(c.getCause()!=null){
|
while(c.getCause()!=null){
|
||||||
Throwable cc= c.getCause();
|
Throwable cc= c.getCause();
|
||||||
if(c.getMessage()==null){
|
if(c.getMessage()==null){
|
||||||
@@ -93,19 +93,19 @@ public class CodeException extends RuntimeException {
|
|||||||
}
|
}
|
||||||
String cMsg=c.getMessage();
|
String cMsg=c.getMessage();
|
||||||
String ccMsg=cc.getMessage();
|
String ccMsg=cc.getMessage();
|
||||||
System.out.println("!!!"+cMsg+"/"+c.getClass().getName()+"/"+cc.getClass().getName());
|
//System.out.println("!!!"+cMsg+"/"+c.getClass().getName()+"/"+cc.getClass().getName());
|
||||||
boolean wrapped=(c instanceof CodeException) && ((CodeException)c).getCode()==ResultCode.FAILURE;
|
boolean wrapped=(c instanceof CodeException) && ((CodeException)c).getCode()==ResultCode.FAILURE;
|
||||||
boolean plain_at=cMsg.equals(c.getClass().getName());
|
boolean plain_at=cMsg.equals(c.getClass().getName());
|
||||||
boolean plain_sub=cMsg.equals(cc.getClass().getName());
|
boolean plain_sub=cMsg.equals(cc.getClass().getName());
|
||||||
boolean same_msg=cMsg.equalsIgnoreCase(ccMsg);
|
boolean same_msg=cMsg.equalsIgnoreCase(ccMsg);
|
||||||
System.out.println("\t"+plain_sub+"#"+cc+"$"+cc.getCause()+"*"+cc.getMessage());
|
//System.out.println("\t"+plain_sub+"#"+cc+"$"+cc.getCause()+"*"+cc.getMessage());
|
||||||
if(plain_at || plain_sub || cMsg.startsWith(cc.getClass().getName()+":") || same_msg || wrapped){
|
if(plain_at || plain_sub || cMsg.startsWith(cc.getClass().getName()+":") || same_msg || wrapped){
|
||||||
c=cc;
|
c=cc;
|
||||||
}else{
|
}else{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("CC:"+c);
|
//System.out.println("CC:"+c);
|
||||||
// take care of title
|
// take care of title
|
||||||
String _title=c.getClass().getSimpleName();
|
String _title=c.getClass().getSimpleName();
|
||||||
if(c instanceof CodeException){
|
if(c instanceof CodeException){
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class DemoApp extends JettyApp implements AppModule{
|
|||||||
Resources.appendSearch(0,cls);
|
Resources.appendSearch(0,cls);
|
||||||
String work_dir=ArgsConfig.APP_WORKDIR.get(conf);
|
String work_dir=ArgsConfig.APP_WORKDIR.get(conf);
|
||||||
if(work_dir!=null) Resources.appendSearch(0,work_dir);
|
if(work_dir!=null) Resources.appendSearch(0,work_dir);
|
||||||
|
log().info("work_dir:{}",work_dir);
|
||||||
//for(Object p:Resources.search_path){
|
//for(Object p:Resources.search_path){
|
||||||
// System.out.println("sp:"+p);
|
// System.out.println("sp:"+p);
|
||||||
//}
|
//}
|
||||||
@@ -52,7 +53,7 @@ public class DemoApp extends JettyApp implements AppModule{
|
|||||||
app.setSecurityPolicy(secpol);
|
app.setSecurityPolicy(secpol);
|
||||||
// install router
|
// install router
|
||||||
app.setRouter(new Router());
|
app.setRouter(new Router());
|
||||||
DemoEP ep=new DemoEP();
|
StatusMod ep=new StatusMod();
|
||||||
ep.publish(app);
|
ep.publish(app);
|
||||||
// install file sever endpoint
|
// install file sever endpoint
|
||||||
FileServer fs=new FileServer("/static","/public");
|
FileServer fs=new FileServer("/static","/public");
|
||||||
@@ -60,6 +61,8 @@ public class DemoApp extends JettyApp implements AppModule{
|
|||||||
Menu top_menu=Menu.request(Menu.TOP);
|
Menu top_menu=Menu.request(Menu.TOP);
|
||||||
top_menu.add(new MenuItem("home")).addSpacer().add(new MenuItem("login"));
|
top_menu.add(new MenuItem("home")).addSpacer().add(new MenuItem("login"));
|
||||||
top_menu.setTitle("Jabba3");
|
top_menu.setTitle("Jabba3");
|
||||||
|
app.getRouter().compile();
|
||||||
|
System.out.println(app.getRouter().regex);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void publish(App app) {
|
public void publish(App app) {
|
||||||
@@ -120,6 +123,7 @@ public class DemoApp extends JettyApp implements AppModule{
|
|||||||
@Routed
|
@Routed
|
||||||
public void login(com.reliancy.jabba.Request req,Response resp){
|
public void login(com.reliancy.jabba.Request req,Response resp){
|
||||||
//return "login form here";
|
//return "login form here";
|
||||||
|
log().info("login here");
|
||||||
if(req.getVerb().equals("POST")){
|
if(req.getVerb().equals("POST")){
|
||||||
// here we need to process login and redirect
|
// here we need to process login and redirect
|
||||||
AppSession ass=AppSession.getInstance();
|
AppSession ass=AppSession.getInstance();
|
||||||
|
|||||||
Reference in New Issue
Block a user