jmHttp Server

Table of Contents

1 jmtthp server - A micro scala/java Http server

1.1 Overview

jmhttp server - is a micro self-contained lightweight http server to share files across local netork. It is useful to access shared files, musics, pictures and directories from other computers, smartphones, tablets and so on. This app can also serve static files at local network·

Features:

  • Self contained: Just one file, one jar file, self-explanatory and easy to use and deploy.
  • No instalation required+, it is ready to use and ready to go.
  • Cross-platform, as it runs on top of the Java Platform. So this server can be run without recompiling and reinstalling on Linux, Mac OSX, BSD or Windows.
  • Serve static website - The server can serve a static web site if there is any file named index.html at the browsed directory.
  • Network service advertising - The server can be advertised at local network and made discoverable as networks printers, scanners, cameras and etc, through zeroconf protocol (aka Apple's Bounjour). So it can be located without knowing its network address.
  • SSL/TSL protocol support - TSL (Transport Secure Layer) or SSL (Secure Socket Layer). It allows the http traffic between the server and browser to be encrypted and secure.
  • Basic Authenticatin login

WARNING:

  • The HTTP traffic without TLS/SSL is not encrypted, therefore, don't use the server without SSL over the internet or at insecure or public local networks.
  • Basic Authentication should not be used without TLS/SSL as the password and login are sent unencrypted as plain text.

1.2 Usage

1.2.1 Show help

The Jmhttp server is self-explanatory as it user-help text is comprehensive and gives lots of examples.

$ java -jar jmhttp-uber.jar 
jmhttp 1.4 - Micro http server for file sharing at local network.
Usage: $ jmhttp [COMMAND] [OPTIONS] [<ARGS> ...]

Commands:

  dir   Share single directory.                 
  mdir  Share multiple directories.             
  echo  Run echo server for debugging purposes

Commands:

  • dir - Share a single directories:
$ java -jar jmhttp-uber.jar dir
Share single directory.

USAGE: $ jmhttp dir <DIRECTORY

OPTIONS:
  -port=<PORT>,                  -p   Port that server will listen to. Default 8080                       
  -host=<HOST>,                  -    Host that server will listen to. Default 0.0.0.0 - All addresses.   
  -auth=<USER>:<PASSWORD>,       -    Authentication - default empty.                                     
  -tls=<KEY STORE>:<PASSWORD>,   -    Enable TLS (Transport Layer Security)/SSL. It encrypts connection.  
  -image,                        -im  Show images thumbnails in directory listing.                        
  -no-index,                     -ni  Don't render index.html if available in directory listing.          
  -publish,                      -    Publish server with multicast DNS (aka mdns, Zeroconf protocol.)    

EXAMPLES:
Share single directory /home/user/Documents at default port 8080
    listening all hosts. Note: (~) tilde is replaced by /home/<user> on Linux,
    /User/<user> on OSX and C:\\User\\<user> on Windows.

    > $ jmhttp dir C:\\Users\\user\\Documents  (Windows)
    > $ jmhttp dir /Users/dummy/documents
      or
    > $ jmhttp ~/Documents

    Share single directory with authentication:

    It will serve the user home directory (~) tilde or /home/<username> on Linux,
    /Users/<username> on MacOSX and C:\\Users\\<username> on Windows with
    authentication requesting username john and password pxjmnf.
    The server will run on the port 8000.

    Note: Even with authentication is still not safe against network sniffers
    such as WireShark. To make the server secure, in addition to authentication,
    it is necessary to use TSL (Transport Secure Layer) option.
    The server can be opened in the web browser at the URL http://localhost:8080
    or http://127.0.0.1:8080 or http://computerIP:8080. When the server is using
    SSL/TLS the server URL is https://<address>:<port>

    > $ jmhttp dir -p=8000 -publish -image -auth=john:pxjmnf tls=cert.jks:pass ~

    Explanation:
        + -p=8000             - Set server port to 8000
        + -publish            - Publish server address on Local network using multicast 
                                DNS or (Zeroconf / Bounjour)
        + -auth=john:pxjmnf   - Basic authentication (user john, password pxmnf)
        + -image              - Show images in the directory listening
        + -tls=cert.jks:pass  - Use the TSL certificate cert.jks to encrypt the connection.
                                <pass> is the certificate's password.

    Note: All command line parameters with (-) dash are optional.


    A TSL/SLL certificate can be generated on Linux or OSX using:

    $ keytool -genkeypair -keyalg RSA -alias sec_server \
       -keystore cert.jks \
       -storepass chargeit -validity 1000000 -keysize 2048
  • mdir - Share multiple directories:
$ java -jar jmhttp-uber.jar mdir
Share multiple directories.

USAGE: $ jmhttp mdir <URL1:DIRECTORY1> [<URL2:DIRECTORY2> ...]

OPTIONS:
  -port=<PORT>,                  -p   Port that server will listen to. Default 8080                       
  -host=<HOST>,                  -    Host that server will listen to. Default 0.0.0.0 - All addresses.   
  -auth=<USER>:<PASSWORD>,       -    Authentication - default empty.                                     
  -tls=<KEY STORE>:<PASSWORD>,   -    Enable TLS (Transport Layer Security)/SSL. It encrypts connection.  
  -image,                        -im  Show images thumbnails in directory listing.                        
  -no-index,                     -ni  Don't render index.html if available in directory listing.          
  -publish,                      -    Publish server with multicast DNS (aka mdns, Zeroconf protocol.)    

EXAMPLES:

    Share multiple directories using port 8090 and announcing server
    through mDNS multicast DNS Discovery service, aka Apple's Bounjour(®)
    or Zeroconf. It will make the directory Documents available at
    http:<addr>:8090/docs and ~/Pictures at http:<addr>:8090/pics.

    > $ jmthtp -p=8090 -publish docs:~/Documents pics:~/Pictures

    Share multiple directories with tsl/ssl (Transport Layer Security/
    Secure Socket Layer) encryption. It changes the server's URL to
    https://<serveraddr>:8080. It is no longer http://...

    > $ jmhttp -p=8080 --tls=cert.jks:password -m docs:~/Documents pics:~/Pictures

   To generate the certificate use:

   $ keytool -genkeypair -keyalg RSA -alias sec_server \
       -keystore cert.jks \
       -storepass chargeit -validity 1000000 -keysize 2048
  • echo - Run server in echo mode. The server answers all requests by printing back the requests data. This command is useful for debugging http clients or learning more about http requests.
$ java -jar jmhttp-uber.jar echo -h
Run echo server for debugging purposes

USAGE: $ jmhttp echo 

OPTIONS:
  -port,   -p  Port that server will listen to. Default 8080                      
  -host,   -   Host that server will listen to. Default 0.0.0.0 - All addresses.  
  -auth,   -   Authentication - default empty.

1.2.2 Running the server

By default, the server binds to port 8080. To change it to another port run with -p=<port number>, for instance, -p=9090 to bind to port 9090.

Example 1

Share the directory /home/archbox/test to ~/test binding the server to port 8080. The shared directory can accessed at http://192.168.1.22:8080 URL.

$ bin/jmhttp /home/archbox/test/
Server running at: http://192.168.0.3:8080
[2017-11-08 13:59:02] [INFO] - jmhttp.server.HttpServer run
 - Starting server at host = 0.0.0.0 and port = 8080 


[2017-11-08 13:59:33] [INFO] - jmhttp.server.HttpServer $anonfun$run$2
 - HTTP Request: path = / - method = GET - address = /0:0:0:0:0:0:0:1 

[2017-11-08 13:59:33] [INFO] - jmhttp.server.HttpServer $anonfun$run$2
 - HTTP Request: path = /favicon.ico - method = GET - address = /0:0:0:0:0:0:0:1 

... ... ... ...

screenshot1.png

screenshot2.png

On windows this sever can be run with:

$ java -jar jmhttp C:\Users\arch\Desktop
# or 
$ java -jar jmhttp ~/Desktop

Example 2

Changing the port that server listen run:

$ jmhttp -p=9090 /home/archbox/test/
Server running at: http://192.168.0.3:9090
[2017-11-08 14:00:43] [INFO] - jmhttp.server.HttpServer run
 - Starting server at host = 0.0.0.0 and port = 9090 

[2017-11-08 14:00:58] [INFO] - jmhttp.server.HttpServer $anonfun$run$2
 - HTTP Request: path = /readerMonad.org - method = GET - address = /0:0:0:0:0:0:0:1 

[2017-11-08 14:00:58] [INFO] - jmhttp.server.HttpServer $anonfun$run$2
 - HTTP Request: path = /favicon.ico - method = GET - address = /0:0:0:0:0:0:0:1

Example 3

Open the server website in the default browser after the server start. It will open the server website at http://192.168.0.3:9090

$ bin/jmhttp --browser -p=9090 /home/archbox/test/
Server running at: http://192.168.0.3:9090
[2017-11-08 14:02:21] [INFO] - jmhttp.server.HttpServer run
 - Starting server at host = 0.0.0.0 and port = 9090 

# Or 

$ jmhttp --b -p=9090 /home/archbox/test/
Server running at: http://192.168.1.22:9090

Example 4

Sharing multiple directories:

It will make the directory contents of /home/archbox/opt be available at the URL http://192.168.1.22:8080/opt and the directory contents of /home/archbox/Documents/wiki be available at http://192.168.1.22:8080/org. If there is any file named index.html in the wiki directory, it will be displayed instead of showing the directory contents.

$ bin/jmhttp -m -b opt:/home/archbox/opt pics:/home/archbox/Pictures org:/home/archbox/Documents/wiki 
Server running at: http://192.168.1.22:8080

screenshot3-shared-dirs.png

screenshot4-index.png

Example 5

Too advertising the server at local network with multicast-DNS, zeroconf (that Apple calls Boujour) just add the flag -publish.

$ bin/jmhttp -publish -p=9090 opt:~/opt pics:~/Pictures org:/home/archbox/Documents/wiki

The advertising with zeroconf allows the server to be accessed without knowing or typing its IP address by using any Zeroconf browser, android app with zeroconf for network service discovery or Mac OSX Safari Zeroconf.

screenshot5-mac-osx-bounjour.png

1.2.3 Dealing with Firewalls

Dealing with Firewall

In order to use the server it is necessary to disable the firewall or create a rule to open the port while testing the server.

  • Dealing with firewall on Windows OS: To opening the port 8080 on Windows > Windows 2008. Open a console cmd.exe as administrator and copy and paste the command below. - Reference: Open TCP Port 80 using Netsh
rem Open TCP Port 8080 inbound and outbound
netsh advfirewall firewall add rule name="jmhttp port 8080" dir=in action=allow protocol=TCP localport=8080
  • Dealing with firewall on Linux OS
# Stop firewall temporarily (Fedora) 
$ systemctl stop firewalld

# Start firewall 
$ systemctl start firewalld

# Disable Firewall from boot. 
$ systemctl disable firewalld

1.3 Building Instructions

1.3.1 Building with sbt

Make sure the latest sbt is available in the system and run $ sbt makesh

Step 1: Enter project root directory.

cd <project-directory>

Step 2: Compile with $ sbt makesh. It generates the file ./jmhttp which is placed at the project current directory;

$ sbt makesh
[info] Loading settings from idea.sbt,plugins.sbt ...
[info] Loading global plugins from /home/archbox/.sbt/1.0/plugins
[info] Loading settings from assembly.sbt ...
[info] Loading project definition from /home/archbox/Documents/projects/jmhttp.scala/project
[info] Loading settings from build.sbt ...
[info] Set current project to jmhttp (in build file:/home/archbox/Documents/projects/jmhttp.scala/)
[info] Including from cache: jmdns-3.4.1.jar
[info] Including from cache: jmhttp-1.4.jar
[info] Including from cache: scala-library.jar
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/INDEX.LIST' with strategy 'discard'
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Merging 'META-INF/maven/javax.jmdns/jmdns/pom.properties' with strategy 'discard'
[warn] Merging 'META-INF/maven/javax.jmdns/jmdns/pom.xml' with strategy 'discard'
[warn] Strategy 'discard' was applied to 4 files
[info] Assembly up to date: /home/archbox/Documents/projects/jmhttp.scala/target/jmhttp-assembly-1.4.jar
Created  = jmhttp
Run it with java -jar jmhttp or ./jmhttp or sh jmhttp
[success] Total time: 4 s, completed Jun 20, 2018 8:48:34 AM

Step 3: Test the server.

$ du -h jmhttp
5.4M    jmhttp
5.4M    total

# Check the header 
#----------------------
$ head -n 15 jmhttp
#!/usr/bin/env sh
# Check if JAVA_HOME is Set 
if [ -n "${JAVA_HOME}" ]
then
    # Check if JAVA is Installed in this JAVA_HOME
    if [ -f  "$JAVA_HOME/bin/java" ] ;
    then
        "$JAVA_HOME/bin/java" -jar "$0" "$@"
    # Try to use JAVA from $PATH Variable
    else
        # Check if Java is Installed 
        if hash java 2>/dev/null;
        then
            java -jar "$0" "$@"
        els

Step 4: Run the program.

# Run as Unix executable 
#-----------------------------------------------------
$ ./jmhttp
jmhttp 1.4 - Micro http server for file sharing at local network.
Usage: $ jmhttp [COMMAND] [OPTIONS] [<ARGS> ...]

Commands:

  dir   Share single directory.                 
  mdir  Share multiple directories.             
  echo  Run echo server for debugging purposes  

# Run as shell script 
#-----------------------------------------------------
$ sh jmhttp
jmhttp 1.4 - Micro http server for file sharing at local network.
Usage: $ jmhttp [COMMAND] [OPTIONS] [<ARGS> ...]

Commands:

  dir   Share single directory.                 
  mdir  Share multiple directories.             
  echo  Run echo server for debugging purposes 

# Run with java -jar 
#-----------------------------------------------------
$ java -jar jmhttp
jmhttp 1.4 - Micro http server for file sharing at local network.
Usage: $ jmhttp [COMMAND] [OPTIONS] [<ARGS> ...]

Commands:

  dir   Share single directory.                 
  mdir  Share multiple directories.             
  echo  Run echo server for debugging purposes

Install:

  • In order to install, it is necessary just to move the server to any directory in the $PATH environment variable. So, in Linux, MacOSX or any other Unix-like OS, the program could be moved to /bin, /usr/bin or ~/bin.

Once installed, the program can be run without ./ or absolute path ./path/jmhttp:

$ jmhttp
jmhttp 1.4 - Micro http server for file sharing at local network.
Usage: $ jmhttp [COMMAND] [OPTIONS] [<ARGS> ...]
  ... ... ... ... .... ....

To install in the user directory without root permission, it is necessary to create the directory:

$ mkdir -p ~/bin

# Add this line to the file ~/.bashrc or ~/.bash_profile 
$ export PATH=$PATH:~/bin

# Move the program to ~/bin
$ mv jmhttp ~/bin 
$ chmod +x ~/bin/jmhttp

1.3.2 Building with jarget

The server requires scala as building dependency and jarget building tool to fetch the dependencies and bundle them with the application.

To get jarget, just run:

$ curl -o ~/bin/jarget -L https://github.com/caiorss/jarget/raw/v2.1.0-beta-release/jarget && chmod +x ~/bin/jarget

To build the server run:

$ make force && make sh-guard

It will generate an unix-executable uber jar, namely "bin/jmhttp"

$ bin/jmhttp 
A micro Java/Scala http server to share files in the local network

Usage: jmhttp [OPTIONS] ... [[DIRECTORY] | [URL:DIRECTORY] [URL:DIRECTORY] ...]

   ... ... ... ... ... ... ... ...... ... ... ...


$ java -jar bin/jmhttp
A micro Java/Scala http server to share files in the local network

Usage: jmhttp [OPTIONS] ... [[DIRECTORY] | [URL:DIRECTORY] [URL:DIRECTORY] ...]

   -h, --help           Display this help and exit
   ... ... ... ... ... ... ... ...... ... ... ...


$ file bin/jmhttp 
bin/jmhttp: a /usr/bin/env sh  script executable (binary data)

$ du -h bin/jmhttp
1.7M    bin/jmhttp
1.7M    total

After building the jarget cache can be removed:

$ jarget cache -jars 
/home/archbox/.jarget/cache/javax/jmdns/jmdns/3.4.1/jmdns-3.4.1.jar

$ jarget cache -path
/home/archbox/.jarget/cache

$ rm -rf /home/archbox/.jarget

1.4 Binary release

The most update version can be downloaded from the link below or using curl.

$ curl -O -L https://github.com/caiorss/jmhttp/raw/gh-pages/jmhttp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   130  100   130    0     0     21      0  0:00:06  0:00:06 --:--:--    42
100 1703k  100 1703k    0     0   121k      0  0:00:14  0:00:14 --:--:--  475k

$ chmod +x jmhttp

$ ./jmhttp --version
jmhttp - v1.0

$ java -jar ./jmhttp --version
jmhttp - v1.0

$ sh ./jmhttp --version
jmhttp - v1.0

1.5 TODO Tasklist and future work

  • [X] - Implement logging
  • [X] - Implement a consistent command line handling.
  • [X] - Add Zeroconf - Network Service advertising.
  • [X] - Add basic HTTP authentication.
  • [X] - Implement cross-platform path expansion.
  • [X] - Implement Image Gallery
  • [ ] - Add cookie-based authentication.
  • [X] - Supoport HTTPS/TLS security extension.
  • [X] - Create Unix daemon wrapper.
  • [X] - Provide GIT-like subcommands.
  • [ ] - [MAYBE] GUI - Graphical User Interface
  • [X] - Create sbt file.
  • [ ] - Implement plain text human-readable configuration file.

Author: Caio Rodrigues

Created: 2018-06-20 Wed 09:19

Emacs 25.3.1 (Org mode 8.2.10)

Validate