All Projects → piotrpolak → Android Http Server

piotrpolak / Android Http Server

Licence: gpl-3.0
A complete zero-dependency implementation of a web server and a servlet container in Java with a sample Android application.

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to Android Http Server

Cppwebframework
​The C++ Web Framework (CWF) is a MVC web framework, Open Source, under MIT License, using C++ with Qt to be used in the development of web applications.
Stars: ✭ 348 (+120.25%)
Mutual labels:  server, servlet, webserver
SnorkTracker
GPS IoT tracker board for scanning gps and environment information and sending this to a MQTT server via GPRS.
Stars: ✭ 38 (-75.95%)
Mutual labels:  webserver, sms
Butterfly Server
The Everything is Real-Time C# Backend for Single Page Applications
Stars: ✭ 247 (+56.33%)
Mutual labels:  server, webserver
Pode
Pode is a Cross-Platform PowerShell web framework for creating REST APIs, Web Sites, and TCP/SMTP servers
Stars: ✭ 329 (+108.23%)
Mutual labels:  server, webserver
Rayo.js
Micro framework for Node.js
Stars: ✭ 170 (+7.59%)
Mutual labels:  server, webserver
learn undertow
learn undertow
Stars: ✭ 27 (-82.91%)
Mutual labels:  webserver, servlet
Binserve
A blazingly fast static web server with routing, templating, and security in a single binary you can set up with zero code. ⚡️🦀
Stars: ✭ 401 (+153.8%)
Mutual labels:  server, webserver
Agoo
A High Performance HTTP Server for Ruby
Stars: ✭ 679 (+329.75%)
Mutual labels:  server, webserver
Glass Isc Dhcp
Glass - ISC DHCP Server Interface
Stars: ✭ 486 (+207.59%)
Mutual labels:  sms, server
Wsgidav
A generic and extendable WebDAV server based on WSGI
Stars: ✭ 476 (+201.27%)
Mutual labels:  server, webserver
Servez
A simple web server for local web development.
Stars: ✭ 124 (-21.52%)
Mutual labels:  server, webserver
Iodine
iodine - HTTP / WebSockets Server for Ruby with Pub/Sub support
Stars: ✭ 720 (+355.7%)
Mutual labels:  server, webserver
Pure Http
✨ The simple web framework for Node.js with zero dependencies.
Stars: ✭ 139 (-12.03%)
Mutual labels:  server, webserver
Uhttpsharp
A very lightweight & simple embedded http server for c#
Stars: ✭ 151 (-4.43%)
Mutual labels:  webserver
Gophertunnel
Toolbox for Minecraft software written in Go
Stars: ✭ 156 (-1.27%)
Mutual labels:  server
Nginx
A fairly flexible and feature full Ansible role for the NGINX web server.
Stars: ✭ 151 (-4.43%)
Mutual labels:  webserver
Rolisteam
Rolisteam is a virtual tabletop. It helps you to manage tabletop role playing games with remote friends/players. It provides many features to share maps, pictures, dice roller, manage background music and much more. The main git repository is available here: [https://invent.kde.org/kde/rolisteam].
Stars: ✭ 151 (-4.43%)
Mutual labels:  server
Pervane
Plain text file based note taking and knowledge base building tool, markdown editor, simple browser IDE.
Stars: ✭ 159 (+0.63%)
Mutual labels:  server
Imageserver
Image server toolkit in Go
Stars: ✭ 1,944 (+1130.38%)
Mutual labels:  server
Crossbar
Crossbar.io - WAMP application router
Stars: ✭ 1,957 (+1138.61%)
Mutual labels:  server

Android HTTP Server

Small but powerful multithreaded web server written completely in Java SE and then ported to Android.

Build Status codecov Codacy Badge

The server implements most of the HTTP 1.1 specification and provides custom servlet API that can be used to handle dynamic pages. The servlet API is designed after the official javax.servlet API yet it is not compatible. Dynamic pages support cookies, sessions, file uploads and anything else to build a common web application.

Key features

  • Small footprint, requires no external libraries
  • Handles HTTP requests in separate threads
  • Provides custom servlets API for generating dynamic content
  • Supports GET, POST, HEAD methods (or more, depending on the configuration)
  • Supports chunked transfer type
  • Provides full support for mime types (uses Apache like mime.type)
  • Supports buffered file upload (multipart requests), cookies, persisted sessions
  • Supports serving partial body (ranges)
  • Can serve static content both from file system and APK resources

Building the application

The provided Gradle wrapper should be used to build the application:

./gradlew clean build

Installing Android SDK from command line

When running the full build for the first time you must first install the Android SDK. You might either install it manually or use the following script that downloads and installs all required dependencies to ~/android-sdk.

./installsdk.sh

To make things work after you logout and login back, configure the ANDROID_HOME environment variable:

echo "export ANDROID_HOME=~/android-sdk" >> ~/.bashrc && source ~/.bashrc

The http subproject and the idea behind it

The http subproject is the heart of the application and it is independent on Android platform.

In fact the Android app was just an attempt to find a more practical use of the experimental HTTP protocol implementation.

One of the design goals was to keep the resulting artifact small in size and minimalistic in terms of dependency on other libraries - it does not require any third party component, all HTTP protocol implementation is based on parsing data read from raw TCP sockets.

Once the ro.polak.http package is mature enough it will be released as an independent artifact.

The subproject can be tested in the following way:

./gradlew :http:clean :http:check -PskipAndroidBuild

The original package code has been refactored and covered with unit and integration tests. Code coverage should be kept above 90%.

codecov

Android SDK compatibility issues

All application code is targeted to Java 7. It also compiles for Android SDK versions < 19 (try with resources is not supported, use IOUtilities.closeSilently(closeable) in a finally block as an alternative when closing streams).

Another compatibility constraint is that Random instead of ThreadLocalRandom is used for generating random sequences in StringUtilities

Mutation testing

Mutation tests can be run by executing the following command:

./gradlew :http:clean :http:pitest -PskipAndroidBuild

The results can then be found under http/build/reports/pitest/ro.polak.http/index.html and http/build/reports/pitest/ro.polak.http/mutation.xml.

Running standalone server (CLI)

Standalone server can be used to bundle the http subproject into a runnable server implementation. The CLI subproject is also independent on the Android platform, it is not bundled with the main APK.

./gradlew :cli:bootRun -PskipAndroidBuild

It is also possible to build one "uber-jar" and to use it as a standalone application:

./gradlew :cli:fatJar -PskipAndroidBuild

The resulting artifact can then be grabbed from ./cli/build/libs/cli-all.jar.

The standalone server jar can be run on any machine with the following command:

java -jar ./cli/build/libs/cli-all.jar

Overwriting configuration values from command line

java -jar ./cli/build/libs/cli-all.jar \
    -Dserver.port=8888 \
    -Dserver.static.path=/www/public_html

For a complete list of available parameters refer to httpd.properties.

Command line interface0

Demo

A demo application is automatically deployed to Heroku and can be reached at:

Please note the deployed application does not contain the admin application since that is only available for Android. See Procfile for the deployment description.

Sample code

Hello World servlet

package example;

import ro.polak.http.servlet.HttpServletRequest;
import ro.polak.http.servlet.HttpServletResponse;
import ro.polak.http.servlet.HttpServlet;

public class HelloWorld extends HttpServlet {

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) {
        response.getWriter().print("Hello World!");
    }
}

Request logging filter

package example;

import java.io.IOException;

import ro.polak.http.exception.ServletException;
import ro.polak.http.servlet.Filter;
import ro.polak.http.servlet.FilterChain;
import ro.polak.http.servlet.FilterConfig;
import ro.polak.http.servlet.HttpServletRequest;
import ro.polak.http.servlet.HttpServletResponse;

public class RequestLoggingFilter implements Filter {
    
    private static final Logger LOGGER = Logger.getLogger(RequestLoggingFilter.class.getName());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // Do nothing
    }

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response,
                         FilterChain filterChain) throws IOException, ServletException {
        
        LOGGER.fine("Handling incoming request " + request.getRequestURL());
        
        filterChain.doFilter(request, response);
    }
}

Example servlets can be found in http/src/main/java/example.

A practical use of filters can be checked at SecurityFilter.java and LogoutFilter.java of the admin application.

Building a deployment descriptor

DeploymentDescriptorBuilder is an API alternative to traditional web.xml approach that aims to make servlet mapping building and filter registration easy. See example code below.

package example;

import java.util.List;
import java.util.regex.Pattern;

import ro.polak.http.configuration.DeploymentDescriptorBuilder;
import ro.polak.http.configuration.ServerConfig;
import ro.polak.http.session.storage.SessionStorage;

class DeploymentDescriptorFactory {
    public List<ServletContextWrapper> buildDeploymentDescriptor(SessionStorage sessionStorage,
                                                    ServerConfig serverConfig) {
        
        return DeploymentDescriptorBuilder.create()
                   .withSessionStorage(sessionStorage)
                   .withServerConfig(serverConfig)
                   .addServletContext()
                       .withContextPath("/example")
                       .addFilter()
                           .withUrlPattern(Pattern.compile("^.*$"))
                           .withUrlExcludedPattern(Pattern.compile("^/(?:Login|Logout)"))
                           .withFilterClass(SecurityFilter.class)
                       .end()
                       .addFilter()
                           .withUrlPattern(Pattern.compile("^/Logout$"))
                           .withFilterClass(LogoutFilter.class)
                       .end()
                       .addServlet()
                           .withUrlPattern(Pattern.compile("^/Index$"))
                           .withServletClass(Index.class)
                       .end()
                       .addServlet()
                           .withUrlPattern(Pattern.compile("^/$"))
                           .withServletClass(Index.class)
                       .end()
                   .end()
                   .build();
    }
}

Serving static contents

Serving static resources is implemented using DefaultServlet

The actual resource loading is implemented by registering an instance ResourceProvider in the server config.

Currently there are two resource providers implemented

Sample dummy implementation of a ResourceProvider

package ro.polak.http.resource.provider;

import ro.polak.http.servlet.impl.HttpServletRequestImpl;
import ro.polak.http.servlet.impl.HttpServletResponseImpl;

import java.io.IOException;

public class DummyResourceProvider implements ResourceProvider {

    /**
     * Tells whether this resource provider can load resource for given path.
     */
    @Override
    public boolean canLoad(final String path) {
        return false; // TODO Add some logic
    }

    /**
     * Loads the resource for the given path by copying the stream to the response.getOutputStream().
     */
    @Override
    public void load(final String path,
                     final HttpServletRequestImpl request,
                     final HttpServletResponseImpl response) throws IOException {

        // TODO Load the stream to response.getOutputStream();
    }

    /**
     * Shuts down the resource provider if necessary, usually closes all open resources.
     */
    @Override
    public void shutdown() {
    }
}

Templating support

The following example presents how to integrate Jtwig templating engine.

First you need to add Jtwig dependency in your gradle file:

// ...
dependencies {
    // ...
    compile 'org.jtwig:jtwig-core:5.87.0.RELEASE'
}
// ...

Then it works out of the box:

package example;

import org.jtwig.JtwigModel;
import org.jtwig.JtwigTemplate;

import ro.polak.http.exception.ServletException;
import ro.polak.http.servlet.HttpServlet;
import ro.polak.http.servlet.HttpServletRequest;
import ro.polak.http.servlet.HttpServletResponse;

public class Templating extends HttpServlet {

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response)
    throws ServletException {
        JtwigTemplate template = JtwigTemplate.inlineTemplate("Hello {{ var }}");
        JtwigModel model = JtwigModel.newModel().with("var", "World");

        template.render(model, response.getOutputStream());
    }
}

Screens

Admin main activity HTTP back-office login HTTP back-office menu

HTTP back-office drive access HTTP back-office server statistics HTTP back-office SMS inbox

500 error page trace in browser

Servlet error 500

Sample script to send SMS using wget command line utility

If you want to send a real SMS please remove "&test=1" from the POST params.

SERVER_IP=192.168.1.1; SERVER_PORT=8080; \
    echo "Phone number:"; read TO; echo "Message:"; read MESSAGE; \
    wget -qO- --post-data "to=$TO&message=$MESSAGE&test=1" \
    http://$SERVER_IP:$SERVER_PORT/api/1.0/sms/send

Icons

Android HTTP server uses icons from the beautifully designed "Farm-Fresh Web Icons" pack by FatCow Web Hosting! These icon sets are licensed under a Creative Commons Attribution 3.0 License.

License

The project is shared upon GNU GPLv3 license.

If you are interested in a dedicated commercial license please drop me a line at piotr [at] polak [dot] ro

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].