• Stars
    star
    196
  • Rank 198,524 (Top 4 %)
  • Language
    Java
  • License
    MIT License
  • Created almost 7 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐Ÿงช HTTP Framework based on expressjs, no dependencies, simple usage. Can be used to quickly spin up an API or serve local files.
Logo

Simple and fast HTTP-Framework with the touch of expressjs

License MIT Support me

State of this project

I created this years ago and I'm no longer actively working with java. If anyone is interested maintaining this (and has experience with java), feel free to leave a comment here. It merely was a proof-of-concept of how we could do things more the "funcional" oriented way and less like big java-frameworks and library use to be (as seen on simple but extremely popular libraries such as expressjs).

Getting Started

Express app = new Express();

app.get("/", (req, res) -> {
   res.send("Hello World");
}).listen(); // Will listen on port 80 which is set as default

Installation

Add the following dependency coordinate from JCenter on your favorite build system:

Download

io.vacco.java-express:java-express:<VERSION>

Routing

DynExpress

Express allows the attaching of request-handler to instance methods via the DynExpress annotation:

// Your main class
import express.Express;
public class Main {
    public static void main(String[] args) {
        Express app = new Express();
        app.bind(new Bindings()); // See class below
        app.listen();
    }
}

// Your class with request handlers
import express.DynExpress;
import express.http.RequestMethod;
import express.http.request.Request;
import express.http.response.Response;
public class Bindings {

    @DynExpress() // Default is context="/" and method=RequestMethod.GET
    public void getIndex(Request req, Response res) {
        res.send("Hello World!");
    }

    @DynExpress(context = "/about") // Only context is defined, method=RequestMethod.GET is used as method
    public void getAbout(Request req, Response res) {
        res.send("About page");
    }

    @DynExpress(context = "/impressum", method = RequestMethod.PATCH) // Both defined
    public void getImpressum(Request req, Response res) {
        res.send("Impressum page was patched");
    }

    @DynExpress(method = RequestMethod.POST) // Only the method is defined, "/" is used as context
    public void postIndex(Request req, Response res) {
        res.send("POST to index");
    }
}

Direct

You can add routes (And middlewares) directly to the Express object to handle requests:

Express app = new Express();

// Sample for home routes
app.get("/", (req, res) -> res.send("Hello index!"));
app.get("/home", (req, res) -> res.send("Homepage"));
app.get("/about", (req, res) -> res.send("About"));

// Sample for user
app.get("/user/login", (req, res) -> res.send("Please login!"));
app.get("/user/register", (req, res) -> res.send("Join now!"));

app.listen();

Directly it also supports methods like POST PATCH DELETE and PUT, others need to be created manually:

Express app = new Express();

// Basic methods
app.get("/user", (req, res) -> res.send("Get an user!"));
app.patch("/user", (req, res) -> res.send("Modify an user!"));
app.delete("/user", (req, res) -> res.send("Delete an user!"));
app.put("/user", (req, res) -> res.send("Add an user!"));

// Example fot the CONNECT method
app.on("/user", "CONNECT", (req, res) -> res.send("Connect!"));

app.listen();

With Router

But it's better to split your code, right? With the ExpressRouter you can create routes and add it later to the Express object:

Express app = new Express() {{

  // Define root greeting
  get("/", (req, res) -> res.send("Hello World!"));

  // Define home routes
  use("/home", new ExpressRouter(){{
    get("/about", (req, res) -> res.send("About page"));
    get("/impressum", (req, res) -> res.send("Impressum page"));
    get("/sponsors", (req, res) -> res.send("Sponsors page"));
  }});

  // Define root routes
  use("/", new ExpressRouter(){{
    get("/login", (req, res) -> res.send("Login page"));
    get("/register", (req, res) -> res.send("Register page"));
    get("/contact", (req, res) -> res.send("Contact page"));
  }});

  // Start server
  listen();
}};

URL Basics

Over the express object you can create handler for all request-methods and contexts. Some examples:

app.get("/home", (req, res) -> {
	// Will match every request which uses the 'GET' method and matches the '/home' path
});

app.post("/login", (req, res) -> {
	// Will match every request which uses the 'POST' method and matches the /login' path
});

URL Parameter

Sometimes you want to create dynamic URL where some parts of the URL's are not static. With the : operator you can create variables in the URL which will be saved later in a HashMap.

Example request: GET /posts/john/all:

app.get("/posts/:user/:description", (req, res) -> {
   String user = req.getParam("user"); // Contains 'john'
   String description = req.getParam("description"); // Contains 'all'
   res.send("User: " + user + ", description: " + description); // Send: "User: john, description: all"
});

URL Parameter Listener

You can also add an event listener when the user called an route which contains an certain parameter.

app.get("/posts/:user/:id", (req, res) -> {
  // Code
});

For example, if we want to check every id before the associated get post etc. handler will be fired, we can use the app.onParam([PARAM]) function:

app.onParam("id", (req, res) -> {
  // Do something with the id parameter, eg. check if it's valid.
});

Now, this function will be called every time when an context is requested which contains the id parameter placeholder.

URL Querys

If you make an request which contains querys, you can access the querys over req.getQuery(NAME).

Example request: GET /posts?page=12&from=john:

app.get("/posts", (req, res) -> {
   String page = req.getQuery("page"); // Contains '12'
   String from = req.getQuery("from"); // Contains 'John'
   res.send("Page: " + page + ", from: " + from); // Send: "Page: 12, from: John"
});

Cookies

With req.getCookie(NAME) you can get an cookie by his name, and with res.setCookie(NAME, VALUE) you can easily set an cookie.

Example request: GET /setcookie:

app.get("/setcookie", (req, res) -> {
   Cookie cookie = new Cookie("username", "john");
   res.setCookie(cookie);
   res.send("Cookie has been set!");
});

Example request: GET /showcookie:

app.get("/showcookie", (req, res) -> {
   Cookie cookie = req.getCookie("username");
   String username = cookie.getValue();
   res.send("The username is: " + username); // Prints "The username is: john"
});

Form data

Over req.getFormQuery(NAME) you receive the values from the input elements of an HTML-Form. Example HTML-Form:

<form action="http://localhost/register" method="post">
   <input description="text" name="email" placeholder="Your E-Mail">
   <input description="text" name="username" placeholder="Your username">
   <input description="submit">
</form>

Attention: Currently, File-inputs don't work, if there is an File-input the data won't get parsed! Now description, for the example below, john in username and [email protected] in the email field. Java code to handle the post request and access the form elements:

app.post("/register", (req, res) -> {
  String email = req.getFormQuery("email");
  String username = req.getFormQuery("username");
  // Process data

  // Prints "E-Mail: [email protected], Username: john"
  res.send("E-Mail: " + email + ", Username: " + username);
});

HTTP Relevant classes

Express

This class represents the entire HTTP-Server, the available methods are:

app.get(String context, HttpRequest handler);                   // Add an GET request handler
app.post(String context, HttpRequest handler);                  // Add an POST request handler
app.patch(String context, HttpRequest handler);                 // Add an PATCH request handler
app.put(String context, HttpRequest handler);                   // Add an PUT request handler
app.delete(String context, HttpRequest handler);                // Add an DELETE request handler
app.all(HttpRequest handler);                                   // Add an handler for all methods and contexts
app.all(String context, HttpRequest handler);                   // Add an handler for all methods but for an specific context
app.all(String context, String method, HttpRequest handler);    // Add an handler for an specific method and context
app.use(String context, String method, HttpRequest handler);    // Add an middleware for an specific method and context
app.use(HttpRequest handler);                                   // Add an middleware for all methods but for an specific context
app.use(String context, HttpRequest handler);                   // Add an middleware for all methods and contexts
app.use(String context, ExpressRouter router);                  // Add an router for an specific root context
app.use(ExpressRouter router);                                  // Add an router for the root context (/)
app.onParam(String name, HttpRequest handler);                  // Add an listener for an specific url parameter
app.getParameterListener();                                     // Returns all parameterlistener
app.get(String key);                                            // Get an environment variable
app.set(String key, String val);                                // Set an environment variable
app.isSecure();                                                 // Check if the server uses HTTPS
app.setExecutor(Executor executor);                             // Set an executor service for the request
app.listen();                                                   // Start the async server on port 80
app.listen(ExpressListener onstart);                            // Start the async server on port 80, call the listener after starting
app.listen(int port);                                           // Start the async server on an specific port
app.listen(ExpressListener onstart, int port);                  // Start the async server on an specific port call the listener after starting
app.stop();                                                     // Stop the server and all middleware worker

Response Object

Over the response object, you have serveral possibility like setting cookies, send an file and more. Below is an short explanation what methods exists: (We assume that res is the Response object)

res.getContentType();                  // Returns the current content type
res.setContentType(MediaType type);    // Set the content type with enum help
res.setContentType(String type);       // Set the content type
res.isClosed();                        // Check if the response is already closed
res.getHeader(String key);             // Get the value from an header field via key
res.setHeader(String key, String val); // Add an specific response header
res.sendAttachment(Path file)          // Sends a file as attachment
res.send(String str);                  // Send a string as response
res.send(Path path);                   // Send a file as response
res.send(byte[] bytes)                 // Send bytes as response
res.send();                            // Send empty response
res.redirect(String location);         // Redirect the request to another url
res.setCookie(Cookie cookie);          // Add an cookie to the response
res.sendStatus(Status status);         // Set the response status and send an empty response
res.getStatus();                       // Returns the current status
res.setStatus(Status status);          // Set the repose status
res.streamFrom(long contentLength, InputStream is, MediaType mediaType) // Send a inputstream with known length and type

The response object calls are comments because you can only call the .send(xy) once each request!

Request Object

Over the Request Object you have access to serveral request stuff (We assume that req is the Request object):

req.getAddress();                 // Returns the INET-Adress from the client
req.getMethod();                  // Returns the request method
req.getPath();                    // Returns the request path
req.getContext();                 // Returns the corresponding context
req.getQuery(String name);        // Returns the query value by name
req.getHost();                    // Returns the request host
req.getContentLength();           // Returns the content length
req.getContentType();             // Returns the content type
req.getMiddlewareContent(String name); // Returns the content from an middleware by name
req.getFormQuerys();              // Returns all form querys
req.getParams();                  // Returns all params
req.getQuerys();                  // Returns all querys
req.getFormQuery(String name);    // Returns the form value by name
req.getHeader(String key);        // Returns the value from an header field by name
req.getParam(String key);         // Returns the url parameter by name
req.getApp();                     // Returns the related express app
req.getCookie(String name);       // Returns an cookie by his name
req.getCookies();                 // Returns all cookies
req.getIp();                      // Returns the client IP-Address
req.getUserAgent();               // Returns the client user agent
req.getURI();                     // Returns the request URI
req.isFresh();                    // Returns true if the connection is fresh, false otherwise (see code inline-doc)
req.isStale();                    // Returns the opposite of req.fresh;
req.isSecure();                   // Returns true when the connection is over HTTPS, false otherwise
req.isXHR();                      // Returns true if the 'X-Requested-With' header field is 'XMLHttpRequest'
req.getProtocol();                // Returns the connection protocol
req.getAuthorization();           // Returns the request authorization
req.hasAuthorization();           // Check if the request has an authorization
req.pipe(OutputStream stream, int buffersize); // Pipe the request body to an outputstream
req.pipe(Path path, int buffersize);           // Pipe the request body to an file
req.getBody();                    // Returns the request inputstream

Middleware

Middleware are one of the most important features of JavaExpress, with middleware you can handle a request before it reaches any other request handler. To create an own middleware you have serveral interfaces:

  • HttpRequest - Is required to handle an request.
  • ExpressFilter - Is required to put data on the request listener.
  • ExpressFilterTask - Can be used for middleware which needs an background thread.

Middlewares work, for you, exact same as request handler. For example an middleware for all request-methods and contexts:

// Global context, matches every request.
app.use((req, res) -> {
  // Handle data
});

You can also filter by request-methods and contexts:

// Global context, you can also pass an context if you want
app.use("/home", "POST", (req, res) -> {
  // Handle request by context '/home' and method 'POST'
});

In addition to that yo can use * which stands for every context or request-method:

// Global context, you can also pass an context if you want
app.use("/home", "*", (req, res) -> {
  // Handle request which matches the context '/home' and all methods.
});

Create own middleware

Now we take a look how we can create own middlewares. Here we create an simple PortParser which parse / extract the port-number for us. We only used HttpRequest and ExpressFilter because we don't need any background thread.

public class PortMiddleware implements HttpRequest, ExpressFilter {

   /**
    * From interface HttpRequest, to handle the request.
    */
   @Override
   public void handle(Request req, Response res) {
      
      // Get the port
      int port = req.getURI().getPort();
      
      // Add the port to the request middleware map
      req.addMiddlewareContent(this, port);

      /**
       * After that you can use this middleware by call:
       *   app.use(new PortMiddleware());
       *   
       * Than you can get the port with:
       *   int port = (Integer) app.getMiddlewareContent("PortParser");
       */
   }

   /**
    * Defines the middleware.
    *
    * @return The middleware name.
    */
   @Override
   public String getName() {
      return "PortParser";
   }
}

Now we can, as we learned above, include it with:

// Global context, you can also pass an context if you want
app.use(new PortMiddleware());

And use it:

app.get("/port-test", (req, res) -> {
  
  // Get the content from the PortParser which we create above
  int port = (Integer) req.getMiddlewareContent("PortParser");
   
  // Return it to the client:
  res.send("Port: " + port);
});

Existing Middlewares

There are already some basic middlewares included, you can access these via static methods provided from Middleware.

CORS

To realize a cors api yu can use the cors middleware.

app.use(Middleware.cors());

You can use CorsOptions to specify origin, methods and more:

CorsOptions corsOptions = new CorsOptions();
corsOptions.setOrigin("https://mypage.com");
corsOptions.setAllowCredentials(true);
corsOptions.setHeaders(new String[]{"GET", "POST"});
corsOptions.setFilter(req -> // Custom validation if cors should be applied);
        
app.use(Middleware.cors());

Provide static Files

If you want to allocate some files, like librarys, css, images etc. you can use the static middleware. But you can also provide other files like mp4 etc.

Example:

 app.use(Middleware.statics("examplepath\\myfiles"));

Now you can access every files in the test_statics over the root adress \. I'ts also possible to set an configuration for the FileProvider:

FileProviderOptionsoptions = new FileProviderOptions();
options.setExtensions("html", "css", "js"); // By default, all are allowed.

/*
 * Activate the fallbacksearch.
 * E.g. if an request to <code>/js/code.js</code> was made but the
 * requested ressource cannot be found. It will be looked for an file called <code>code</code>
 * and return it.
 *
 *  Default is false
 */
options.setFallBackSearching(true);
options.setHandler((req, res) -> {...});    // Can be used to handle the request before the file will be returned.
options.setLastModified(true);              // Send the Last-Modified header, by default true.
options.setMaxAge(10000);                   // Send the Cache-Control header, by default 0.
options.setDotFiles(DotFiles.DENY);         // Deny access to dot-files. Default is IGNORE.
app.use(Middleware.statics("examplepath\\myfiles", new FileProviderOptions())); // Using with StaticOptions

Cookie Session

There is also an simple cookie-session implementation:

// You should use an meaningless cookie name for serveral security reasons, here f3v4.
// Also you can specify the maximum age of the cookie from the creation date and the file types wich are actually allowed.
app.use(Middleware.cookieSession("f3v4", 9000));

To use a session cookie we need to get the data from the middleware which is actually an SessionCookie:

 // Cookie session example
app.get("/session", (req, res) -> {

   /**
   * CookieSession named his data "Session Cookie" which is
   * an SessionCookie so we can Cast it.
   */
   SessionCookie sessionCookie = (SessionCookie) req.getMiddlewareContent("sessioncookie");
   int count;
   
Check if the data is null, we want to implement an simple counter
   if (sessionCookie.getData() == null) {
   
      // Set the default data to 1 (first request with this session cookie)
      count = (Integer) sessionCookie.setData(1);
   
   } else {
      // Now we know that the cookie has an integer as data property, increase it
      count = (Integer) sessionCookie.setData((Integer) sessionCookie.getData() + 1);
   }

Send an info message
   res.send("You take use of your session cookie " + count + " times.");
});

Global Variables

Java-express also supports to save and read global variables over the Express instance.

app.set("my-data", "Hello World");
app.get("my-data"); // Returns "Hello World"

Examples

Very simple static-website

// Create instance
new Express() {{
  
  // Define middleware-route for static site
  use("/", Middleware.statics("my-website-folder/"));
}};

File download

// Your file
Path downloadFile = Paths.get("my-big-file");

// Create instance
new Express() {{

  // Create get-route where the file can be downloaded
  get("/download-me", (req, res) -> res.sendAttachment(downloadFile));
}};

Send cookies

new Express() {{

  // Define route
  get("/give-me-cookies", (req, res) -> {
  
    // Set an cookie (you can call setCookie how often you want)
    res.setCookie(new Cookie("my-cookie", "Hello World!"));
    
    // Send text
    res.send("Your cookie has been set!");
  });
}};

License

This project is licensed under the MIT License - see the LICENSE file for details.

More Repositories

1

pickr

๐ŸŽจ Flat, simple, multi-themed, responsive and hackable Color-Picker library. No dependencies, no jQuery. Compatible with all CSS Frameworks e.g. Bootstrap, Materialize. Supports alpha channel, rgba, hsla, hsva and more!
JavaScript
4,290
star
2

selection

โœจ Viselect - A high performance and lightweight library to add a visual way of selecting elements, just like on your Desktop. Zero dependencies, super small. Support for major frameworks!
TypeScript
2,494
star
3

nanopop

๐Ÿฆ Minimalistic, small, positioning engine. Build for high-performance, minimal footprint and maximum control over positioning behavior.
TypeScript
643
star
4

candy

๐Ÿญ Cross-platform YouTube-downloader with playlist and channel support as well as build-in audio / video converter.
Vue
237
star
5

presentr

Minimalistic javascript presentation-library. Zero dependencies. Can be used in combination with frameworks like Bootstrap, Materialize, Vue etc.
JavaScript
71
star
6

openvpn-pihole

๐Ÿ•ต๏ธ A truly delicious combination of two wonderful pieces of software to setup a pi.hole-backed VPN as quick as possible.
Shell
68
star
7

gpickr

Demo of pickr integrated into another widget. A gradient-picker.
JavaScript
60
star
8

ocular

๐Ÿ’ฐ Simplistic, beautiful and straight-forward budgeting app to track your budget across the years. Easy to use, to get started and to set up.
Vue
59
star
9

sassyfication

๐Ÿ’…Library with sass mixins to speed up your css workflow.
SCSS
58
star
10

graceful-ws

๐Ÿ”Œ Graceful WebSocket wrapper with connection re-establishment capabilities.
TypeScript
41
star
11

li18nt

๐ŸŒŽ Lint your i18n translation files. Detect conflicting properties, duplicates and make it more readable and easier to maintain by formatting it!
TypeScript
38
star
12

nason

๐Ÿ“ฆ Ultra tiny serializer / encoder with plugin-support. Useful to build binary files containing images, strings, numbers and more!
TypeScript
35
star
13

vite-plugin-optimize-css-modules

๐Ÿ—œ Mangle / minimize css module classnames in production like facebook and Google do!
TypeScript
28
star
14

cinematic

๐Ÿ“ฝ๏ธ Ultra tiny library to add cinematics to your HTML5 videos!
TypeScript
22
star
15

conway

๐Ÿ•น Supercharged version of conways game-of-life brought to life by wasm and workers.
TypeScript
12
star
16

spectrum

๐ŸŽ™๏ธ Fast, installable, in-browser audio spectrum visualizer. Support for both realtime and audio files!
TypeScript
11
star
17

bavary

๐Ÿงฌ Regular expressions on steroids. Parse anything and everything with a syntax - crafted to parse syntax. A super-set of regular-expressions.
TypeScript
10
star
18

eslint-plugin-align-import

โš™ ESLint plugin to align all your import statements.
JavaScript
8
star
19

ocular-docker

Ready-to-use docker compose setup for ocular โœจ
Shell
8
star
20

widgetify

Simple widget library which helps to quickly create a new, responsive, interactive widget or ui tool.
JavaScript
7
star
21

intl-demo

Interactive demo of the ECMAScript Internationalization API
JavaScript
5
star
22

yuppee

โš™๏ธ Type-safe migration library to migrate data from one schema to another.
TypeScript
4
star
23

reinisch.io

๐Ÿ”ฒ My Personal Homepage :)
TypeScript
3
star
24

reactivity-playground

๐Ÿ’ซ Simple recreation of reactivity as its mainly used in Vue3
TypeScript
3
star
25

cssvjs

Fast, spec-conform css-value parser written entirely in vanilla JavaScript. Can be used in any environment.
JavaScript
3
star
26

cleanup-files

๐Ÿงผ Small utilities to cleanup directories such as download which are all the time full of random stuff.
Rust
1
star
27

genesis

๐Ÿงž A simple, generic, fast and lightweight json api for frontend apps. Store your frontend-data as-is without messing around with a database!
Go
1
star
28

bavary-webpack-loader

Webpack loader for bavary declarations
JavaScript
1
star
29

eslint-config-simon

โš™ Eslint config files for my personal projects.
JavaScript
1
star
30

previous-index-of

Find the previous index of a char-sequence at a given offset in a string
JavaScript
1
star
31

bavary-cli

Bavary CLI
TypeScript
1
star