├── .gitignore
├── README.md
├── ceylon-http-server
├── README.md
├── favicon.ico
├── index.html
└── source
│ └── com
│ └── zt
│ ├── classes.ceylon
│ ├── module.ceylon
│ ├── package.ceylon
│ └── run.ceylon
├── clojure-http-server
├── README.md
├── project.clj
└── src
│ └── clojure_http_server
│ └── core.clj
├── fantom-http-server
├── .buildpath
├── .classpath
├── .project
├── README.md
├── build.fan
└── fan
│ └── HttpServer.fan
├── groovy-http-server
├── index.html
└── src
│ └── org
│ └── zeroturnaround
│ └── HttpServer.groovy
├── kotlin-http-server
└── KotlinHTTPServer
│ ├── HTTPServer.iml
│ └── src
│ ├── HTTPServer.kt
│ ├── HTTPServer2.kt
│ └── index.html
├── scala-http-server
├── README.textile
├── index.html
├── pom.xml
└── src
│ └── main
│ └── scala
│ └── org
│ └── zeroturnaround
│ └── HttpServer.scala
└── xtend-http-server
├── src
├── com
│ └── zt
│ │ └── HttpServer.xtend
└── index.html
└── xtend-gen
└── com
└── zt
└── HttpServer.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Package Files #
4 | *.jar
5 | *.war
6 | *.ear
7 |
8 | bin/
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Examples for JVM Languages Report
2 | =================================
3 |
4 | This is a combined repository for the JVM languages report by RebelLabs. The repository includes a sample HTTP server implementation in different JVM langauges: Clojure, Fantom, Groovy, Kotlin, Scala, Xtend. Feel free to contribute!
5 |
--------------------------------------------------------------------------------
/ceylon-http-server/README.md:
--------------------------------------------------------------------------------
1 | ceylon-http-server
2 | ==================
3 |
4 | Example source code for a blog post: http://zeroturnaround.com/labs/the-adventurous-developers-guide-to-jvm-languages-ceylon
--------------------------------------------------------------------------------
/ceylon-http-server/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeroturnaround/jvm-languages-report/0c2f644f91f3ef0ab25be35ae201a57eec606090/ceylon-http-server/favicon.ico
--------------------------------------------------------------------------------
/ceylon-http-server/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | blah
4 |
5 |
6 | Hello!aasdasd
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ceylon-http-server/source/com/zt/classes.ceylon:
--------------------------------------------------------------------------------
1 | import java.net { Socket }
2 | import java.io { File, BufferedReader, InputStreamReader, PrintWriter, BufferedOutputStream, FileInputStream }
3 | import java.util { StringTokenizer, Date }
4 | import java.lang { Runnable }
5 | import ceylon.interop.java { createByteArray }
6 |
7 | doc "My little HTTP server"
8 | shared class HTTPServer(Socket socket) satisfies Runnable {
9 |
10 | shared File webRoot = File(".");
11 | shared String defaultFile = "index.html";
12 |
13 |
14 | shared actual void run() {
15 | value bufferedReader = BufferedReader(InputStreamReader(socket.inputStream));
16 | value printWriter = PrintWriter(socket.outputStream);
17 | value bufferedOutputStream = BufferedOutputStream(socket.outputStream);
18 |
19 | String? input = bufferedReader.readLine();
20 |
21 | if(!exists input){
22 | return;
23 | }
24 |
25 | value parse = StringTokenizer(input);
26 | value method = parse.nextToken().uppercased;
27 | variable String fileRequested := parse.nextToken().lowercased;
28 |
29 | // methods other than GET and HEAD are not implemented
30 | if (!method.equals("GET") && !method.equals("HEAD")) {
31 | // send Not Implemented message to client
32 | printWriter.println("HTTP/1.0 501 Not Implemented");
33 | printWriter.println("Server: Java HTTP Server 1.0");
34 | printWriter.println("Date: " Date() "");
35 | printWriter.println("Content-Type: text/html");
36 | printWriter.println(); // blank line between headers and content
37 | printWriter.println("");
38 | printWriter.println("Not Implemented");
39 | printWriter.println("");
40 | printWriter.println("501 Not Implemented: " method " method.
");
41 | printWriter.println("");
42 | printWriter.flush();
43 | return;
44 | }
45 |
46 | if (fileRequested.endsWith("/")) {
47 | // append default file name to request
48 | fileRequested += defaultFile;
49 | }
50 |
51 | // create file object
52 | value file = File(webRoot, fileRequested);
53 | // get length of file
54 | value fileLength = file.length();
55 |
56 | // get the file's MIME content type
57 | String content = getContentType(fileRequested);
58 |
59 |
60 | // if request is a GET, send the file content
61 | if (method.equals("GET")) {
62 | Array fileData = createByteArray(fileLength);
63 | //Array fileData = arrayOfSize { size = fileLength; element = 0; };
64 |
65 | value fileIn = FileInputStream(file);
66 | fileIn.read(fileData);
67 |
68 | // send HTTP headers
69 | printWriter.println("HTTP/1.0 200 OK");
70 | printWriter.println("Server: Java HTTP Server 1.0");
71 | printWriter.println("Date: " Date() "");
72 | printWriter.println("Content-type: " content "");
73 | printWriter.println("Content-length: " file.length() "");
74 | printWriter.println(); // blank line between headers and content
75 | printWriter.flush(); // flush character output stream buffer
76 |
77 | bufferedOutputStream.write(fileData, 0, fileLength);
78 | bufferedOutputStream.flush(); // flush binary output stream buffer
79 | }
80 | }
81 |
82 | String getContentType(String fileRequested) {
83 | if (fileRequested.endsWith(".htm") || fileRequested.endsWith(".html")) {
84 | return "text/html";
85 | } else if (fileRequested.endsWith(".gif")) {
86 | return "image/gif";
87 | } else if (fileRequested.endsWith(".jpg")
88 | || fileRequested.endsWith(".jpeg")) {
89 | return "image/jpeg";
90 | } else if (fileRequested.endsWith(".class")
91 | || fileRequested.endsWith(".jar")) {
92 | return "applicaton/octet-stream";
93 | } else {
94 | return "text/plain";
95 | }
96 | }
97 |
98 | }
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/ceylon-http-server/source/com/zt/module.ceylon:
--------------------------------------------------------------------------------
1 | module com.zt '1.0.0' {
2 | import ceylon.interop.java '0.4.1';
3 | import java.base '7';
4 | }
5 |
--------------------------------------------------------------------------------
/ceylon-http-server/source/com/zt/package.ceylon:
--------------------------------------------------------------------------------
1 | shared package com.zt;
2 |
--------------------------------------------------------------------------------
/ceylon-http-server/source/com/zt/run.ceylon:
--------------------------------------------------------------------------------
1 | import java.net { ServerSocket, Socket }
2 | import java.lang { Thread }
3 |
4 | shared Integer port = 8080;
5 |
6 | void run(){
7 | ServerSocket server = ServerSocket(port);
8 | print("Listening for connections on port " port "...");
9 |
10 | while(true){
11 | Socket socket = server.accept();
12 | print("New client connection accepted!");
13 | HTTPServer httpServer = HTTPServer(socket);
14 |
15 | Thread threadRunner = Thread(httpServer);
16 | threadRunner.start();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/clojure-http-server/README.md:
--------------------------------------------------------------------------------
1 | clojure-http-server
2 | ===================
3 |
4 | An simple file based HTTP server in Clojure
--------------------------------------------------------------------------------
/clojure-http-server/project.clj:
--------------------------------------------------------------------------------
1 | (defproject clojure-http-server "1.0.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :dependencies [[org.clojure/clojure "1.3.0"]]
4 | :main clojure-http-server.core)
5 |
--------------------------------------------------------------------------------
/clojure-http-server/src/clojure_http_server/core.clj:
--------------------------------------------------------------------------------
1 | (ns clojure-http-server.core
2 | (:require clojure.string)
3 | (:import
4 | java.util.Date
5 | [java.net ServerSocket SocketException ]
6 | [java.io File RandomAccessFile PrintWriter BufferedReader InputStreamReader BufferedOutputStream]))
7 |
8 | (def web-root ".")
9 | (def default-file "index.html")
10 |
11 | (defn print-to-stream [client-socket byte-content & params]
12 | (let [out (new BufferedOutputStream (.getOutputStream client-socket))
13 | print-out (new PrintWriter out)]
14 | (doseq [param params]
15 | (.println print-out param))
16 | (.println print-out)
17 | (.flush print-out)
18 | (.write out byte-content)
19 | (.flush out)))
20 |
21 |
22 | (defn send-http-response
23 | "Send data to client"
24 | [client-socket status content-type byte-content]
25 | ;; with-open will close the stream for you
26 | (print-to-stream client-socket
27 | byte-content
28 | status
29 | "Server: Clojure HTTP Server 1.0"
30 | (new Date)
31 | (str "Content-type: " content-type)
32 | (str "Content-length " (count byte-content))))
33 |
34 | (defn send-html-response
35 | "Html response"
36 | [client-socket status title body]
37 | (let [html (str "" title "" body "")]
38 | (send-http-response client-socket status "text/html" (.getBytes html "UTF-8"))))
39 |
40 |
41 | (defn read-file
42 | "Reads a binary file into a buffer"
43 | [file-to-read]
44 | (with-open [file (new RandomAccessFile file-to-read "r")]
45 | (let [buffer (byte-array (.length file-to-read))]
46 | (.read (clojure.java.io/input-stream file-to-read) buffer)
47 | buffer)))
48 |
49 | (defn find-content-type
50 | "Simple file type mappings"
51 | [filename]
52 | (let [ext (.substring filename (.lastIndexOf filename ".") (count filename))]
53 | (or
54 | (-> #(some #{ext} (first %))
55 | (filter
56 | [[[".html" ".htm"] "text/html"]
57 | [[".gif"] "image/gif"]
58 | [[".jpg" ".jpeg"] "image/jpeg"]
59 | [[".class" ".jar"] "applicaton/octet-stream"]])
60 | first
61 | second)
62 | "text/plain")))
63 |
64 | (defn not-implemented [client-socket http-method]
65 | (send-html-response client-socket "HTTP/1.1 501 Not Implemented" "Not Implemented" (str "501 Not Implemented: " http-method " method.
"))
66 | (println "501 Not Implemented:" http-method "method"))
67 |
68 |
69 | (defn send-file
70 | "Reads a file from the file system and writes it to the socket"
71 | [client-socket file http-method retry]
72 | (let [dir? (.isDirectory file)]
73 | (cond
74 | (not= http-method "GET")
75 | (not-implemented client-socket http-method)
76 |
77 | (not (.exists file))
78 | (send-html-response client-socket "HTTP/1.1 404 Not Found" "Found" (str "404 Not Found: " (.getName file) "
"))
79 |
80 | (and dir? (not retry))
81 | (send-file client-socket (new File file default-file) http-method true)
82 |
83 | :else
84 | (let [content (read-file file)
85 | content-type (find-content-type (.getName file))]
86 | (send-http-response client-socket "HTTP/1.0 200 OK" content-type content)
87 | (println "File" (.getPath file) "of type" content-type "returned")))))
88 |
89 | (defn process-request
90 | "Parse the HTTP request and decide what to do"
91 | [client-socket]
92 | (let [reader (clojure.java.io/reader client-socket)
93 | first-line (.readLine reader)
94 | tokens (if first-line (clojure.string/split first-line #"\s+"))]
95 | (println "line" first-line "tokens" tokens)
96 | (let [http-method (clojure.string/upper-case (get tokens 0 "unknown"))]
97 | (if (or (= http-method "GET") (= http-method "HEAD"))
98 | (let [file-requested-name (get tokens 1 "not-existing")
99 | file-requested (new File web-root file-requested-name)]
100 | (send-file client-socket file-requested http-method false))
101 | (not-implemented client-socket http-method)) )))
102 |
103 |
104 | (defn respond-to-client
105 | "A new http client is connected. Process the request"
106 | [server-socket]
107 | (println "A client has connected" (new Date))
108 | (with-open [client-socket (.accept server-socket)]
109 | (process-request client-socket))
110 | (println "Connection closed"))
111 |
112 | (defn new-worker
113 | "Spawn a new thread"
114 | [server-socket]
115 | (.start (new Thread (fn [] (respond-to-client server-socket)))))
116 |
117 | (defn -main
118 | "The main method that runs via lein run"
119 | []
120 | (let [port 8080
121 | server-socket (new ServerSocket port)]
122 | (println "Listening for connections on port" port)
123 | (while true
124 | (new-worker server-socket))))
125 |
--------------------------------------------------------------------------------
/fantom-http-server/.buildpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/fantom-http-server/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fantom-http-server/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | FantomHttpServer
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.dltk.core.scriptbuilder
15 |
16 |
17 |
18 |
19 |
20 | com.xored.fanide.core.nature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/fantom-http-server/README.md:
--------------------------------------------------------------------------------
1 | fantom-http-server
2 | ==================
3 |
4 | Simple HTTP Server written in Fantom (http://fantom.org/)
5 |
--------------------------------------------------------------------------------
/fantom-http-server/build.fan:
--------------------------------------------------------------------------------
1 | using build
2 | class Build : build::BuildPod
3 | {
4 | new make()
5 | {
6 | podName = "FantomHttpProject"
7 | summary = ""
8 | srcDirs = [`./`, `fan/`]
9 | depends = ["build 1.0", "sys 1.0", "util 1.0", "concurrent 1.0"]
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/fantom-http-server/fan/HttpServer.fan:
--------------------------------------------------------------------------------
1 | //used pods
2 | using util
3 | using concurrent
4 | //interop
5 | using [java]fanx.interop::Interop
6 |
7 | //java stuff
8 | using [java]java.net::Socket
9 | using [java]java.net::ServerSocket
10 |
11 | class HttpServerMain : AbstractMain
12 | {
13 | @Opt { help = "Http port"; aliases=["p"] }
14 | Int port := 8080
15 |
16 | const ActorPool actorPool := ActorPool { maxThreads = 32 }
17 |
18 | override Int run()
19 | {
20 | serverSocket := ServerSocket(port)
21 | log.info("Listening for connections on port: $port")
22 | try {
23 | while(true) {
24 | socket := serverSocket.accept
25 | a := ServerActor(actorPool)
26 | //wrap a mutable socket to sign that we know what are we doing
27 | a.send(Unsafe(socket))
28 | }
29 | }
30 | catch (Err e) {
31 | serverSocket.close
32 | log.err("Fatal error: $e.msg", e)
33 | return 1
34 | }
35 | throw Err("Shouldn't be here, above is an infinite loop or return. Consult the author :)")
36 | }
37 | }
38 |
39 | const class ServerActor : Actor {
40 | const static ContentType contentTypes := ContentType()
41 | const static Str OUT := "serverActor.out"
42 |
43 | const static Uri defaultFile := Uri("index.html")
44 |
45 | static Log log() { Log.get("ServerActor") }
46 |
47 | new make(ActorPool p) : super(p) {}
48 |
49 | override Obj? receive(Obj? msg) {
50 | // Unsafe is just a wrapper, get the socket
51 | log.info("Accepted a socket: $DateTime.now")
52 | Socket socket := ((Unsafe) msg).val
53 | //get streams
54 | InStream in := Interop.toFan(socket.getInputStream)
55 | OutStream out := Interop.toFan(socket.getOutputStream)
56 | try {
57 | // store output stream
58 | Actor.locals[OUT] = out
59 | query := in.readLine.split()
60 | method := query[0]
61 | file := query[1]
62 | // serve it
63 | sendFile(File(Uri.fromStr("." + file)), method);
64 | }
65 | catch (ServerErr e) {
66 | log.err("Unable to send file for download: $e.msg")
67 | sendHtml(e.returnCode, e.status, e.title, e.msg)
68 | }
69 | finally {
70 | out.close
71 | //clear it from locals
72 | Actor.locals[OUT] = null
73 | }
74 |
75 | //this one doesn't matter, we're flushed our response for good
76 | return null;
77 | }
78 |
79 | Void sendFile(File? file, Str method) {
80 | log.info("Serving ($method) file: $file")
81 | if(!"GET".equals(method) && !"HEAD".equals(method)) {
82 | throw ServerErr(501, "Not Implemented", "Not Implemented", "501 Not Implemented: ${method} method.
")
83 | }
84 |
85 | if(file == null) {
86 | throw ServerErr(400, "Bad Request", "Bad Request", "Cannot parse query part")
87 | }
88 |
89 | if(file.isDir) {
90 | return sendFile(file.plus(defaultFile, true), method)
91 | }
92 | if(!file.exists) {
93 | throw ServerErr(404, "Not Found", "File not found", "Did my best, still cannot find the file: $file, sorry")
94 | }
95 |
96 | content := Buf()
97 | if("GET".equals(method)) {
98 | content = file.readAllBuf
99 | }
100 |
101 | sendHttp(200, "OK", getContentType(file.name), content)
102 | }
103 |
104 | Void sendHtml(Int returnCode, Str status, Str title, Str body) {
105 | html := "
106 | $title
107 |
108 | $body
109 |
110 | "
111 | sendHttp(returnCode, status, "text/html", html.toBuf)
112 | }
113 |
114 | Void sendHttp(Int returnCode, Str status, Str contentType, Buf content) {
115 | OutStream out := Actor.locals[OUT]
116 | // mind the newlines
117 | header :=
118 | "HTTP/1.1 $returnCode $status
119 | Server: Fantom HTTP Server 1.0
120 | Date: ${DateTime.now}
121 | Content-type: ${contentType}
122 | Content-length: ${content.size}
123 |
124 | ".toBuf
125 |
126 | out.writeBuf(header)
127 | out.writeBuf(content)
128 | }
129 |
130 | // maybe a dict would be more readable
131 | Str getContentType(Str filename) {
132 | contentTypes[filename]
133 | }
134 | }
135 |
136 | const class ServerErr : Err {
137 | const Int returnCode
138 | const Str status
139 | const Str title
140 | new make(Int returnCode, Str status, Str title, Str body) : super(body) {
141 | this.returnCode = returnCode
142 | this.status = status
143 | this.title = title
144 | }
145 | }
146 |
147 | const class ContentType {
148 | @Operator Str get(Str name) {
149 | if (name.endsWith(".htm") || name.endsWith(".html")) {
150 | return "text/html"
151 | } else if (name.endsWith(".gif")) {
152 | return "image/gif"
153 | } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
154 | return "image/jpeg"
155 | } else if (name.endsWith(".class") || name.endsWith(".jar")) {
156 | return "applicaton/octet-stream"
157 | } else {
158 | return "text/plain"
159 | }
160 | }
161 | }
--------------------------------------------------------------------------------
/groovy-http-server/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Groovy HTTP Server
4 |
5 |
6 | Hello!
7 |
8 |
--------------------------------------------------------------------------------
/groovy-http-server/src/org/zeroturnaround/HttpServer.groovy:
--------------------------------------------------------------------------------
1 | package org.zeroturnaround
2 |
3 | class HttpServer implements Runnable {
4 | final static webRoot = new File(".")
5 | final static defaultFile = "index.html"
6 |
7 | private final socket;
8 |
9 | HttpServer(socket) {
10 | this.socket = socket;
11 | }
12 |
13 | @Override
14 | void run() {
15 | println "Connection opened. (${new Date()})"
16 |
17 | def input = new BufferedReader(new InputStreamReader(socket.inputStream))
18 | def requestLine = input.readLine()
19 | if (requestLine != null) {
20 | def parse = new StringTokenizer(requestLine)
21 | def method = parse.nextToken().toUpperCase()
22 |
23 | if (method != "GET" && method != "HEAD") {
24 | sendHtmlResponse(
25 | status: "HTTP/1.1 501 Not Implemented",
26 | title: "Not Implemented",
27 | body: "501 Not Implemented: ${method} method.
")
28 |
29 | println "501 Not Implemented: ${method} method."
30 | } else {
31 | def fileRequested = new URLDecoder().decode(parse.nextToken(), "UTF-8")
32 | sendFile(new File(webRoot, fileRequested), method)
33 | }
34 | }
35 |
36 | println "Connection closed."
37 | }
38 |
39 | private def lineSeparator = System.getProperty("line.separator");
40 |
41 | private def sendHttpResponse(status, contentType, content) {
42 | def out = new BufferedOutputStream(socket.outputStream)
43 |
44 | def header = [status,
45 | "Server: Groovy HTTP Server 1.0",
46 | "Date: ${new Date()}",
47 | "Content-type: ${contentType}",
48 | "Content-length: ${content.length}"]
49 | .join(lineSeparator)
50 | .concat(lineSeparator + lineSeparator)
51 | .bytes
52 |
53 | out.write(header);
54 | out.flush()
55 |
56 | out.write(content)
57 | out.flush()
58 |
59 | socket.outputStream.close()
60 | }
61 |
62 | private def sendHtmlResponse(params) {
63 | def html = """\
64 |
65 | ${params.title}
66 |
67 | ${params.body}
68 |
69 | """
70 |
71 | sendHttpResponse(params.status, "text/html", html.getBytes("UTF-8"))
72 | }
73 |
74 | private def sendFile(file, method, isRetry = false) {
75 | def isDir = file.isDirectory()
76 |
77 | if (isDir && !isRetry) {
78 | sendFile(new File(file, defaultFile), method, true)
79 | return
80 | }
81 |
82 | if (file.exists() && !isDir) {
83 | def content = (method == "GET") ? file.readBytes() : new byte[0]
84 |
85 | def contentType = getContentType(file.name)
86 |
87 | sendHttpResponse(
88 | "HTTP/1.0 200 OK",
89 | contentType,
90 | content)
91 |
92 | println "File ${file.path} of type ${contentType} returned."
93 | } else {
94 | sendHtmlResponse(
95 | status: "HTTP/1.0 404 Not Found",
96 | title: "File Not Found",
97 | body: "404 File Not Found: ${file.name}
")
98 |
99 | println "404 File Not Found: ${file.name}"
100 | }
101 | }
102 |
103 | private def getContentType(filename) {
104 | if (filename.endsWith(".htm") || filename.endsWith(".html")) {
105 | return "text/html"
106 | } else if (filename.endsWith(".gif")) {
107 | return "image/gif"
108 | } else if (filename.endsWith(".jpg")
109 | || filename.endsWith(".jpeg")) {
110 | return "image/jpeg"
111 | } else if (filename.endsWith(".class")
112 | || filename.endsWith(".jar")) {
113 | return "applicaton/octet-stream"
114 | } else {
115 | return "text/plain"
116 | }
117 | }
118 |
119 |
120 | public static void main(String[] args) {
121 | def port = 8080
122 | def server = new ServerSocket(port)
123 |
124 | println "Listening for connections on port ${port}..."
125 |
126 | while (true) {
127 | def socket = server.accept()
128 | def thread = new Thread(new HttpServer(socket))
129 | thread.start()
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/kotlin-http-server/KotlinHTTPServer/HTTPServer.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/kotlin-http-server/KotlinHTTPServer/src/HTTPServer.kt:
--------------------------------------------------------------------------------
1 | package httpServer
2 | /**
3 | * Created with IntelliJ IDEA.
4 | * User: maples
5 | * Date: 15/01/2013
6 | * Time: 12:49
7 | */
8 | import java.io.*
9 | import java.net.*
10 | import java.util.StringTokenizer
11 | import java.util.Date
12 |
13 | public class HttpServer(val connect : Socket) : Runnable {
14 |
15 | val WEB_ROOT : File = File(".")
16 | val DEFAULT_FILE : String = "index.html"
17 |
18 | public override fun run() : Unit {
19 | System.out.println("Connection opened. (" + Date() + ")")
20 |
21 | val input = BufferedReader(InputStreamReader(connect.getInputStream()!!))
22 |
23 | input use
24 | {
25 | val requestLine = input.readLine()
26 | if (requestLine != null)
27 | {
28 | val parse : StringTokenizer = StringTokenizer(requestLine)
29 | val method : String = parse.nextToken().toUpperCase()
30 |
31 | if (method != "GET" && method != "HEAD")
32 | {
33 | connect.sendHtmlResponse(
34 | status = "HTTP/1.1 501 Not Implemented",
35 | title = "Not Implemented",
36 | body = "501 Not Implemented: " + method + " method.
")
37 |
38 | System.out.println("501 Not Implemented: " + method + " method.")
39 | }
40 | else
41 | {
42 | val fileRequested = URLDecoder.decode(parse.nextToken(), "UTF-8")
43 | connect.sendFile(File(WEB_ROOT, fileRequested), method)
44 | }
45 | }
46 | }
47 |
48 | System.out.println("Connection closed.\n")
49 | }
50 |
51 | val lineSeparator = System.getProperty("line.separator")!!;
52 |
53 | private fun Socket.sendHttpResponse(status: String,
54 | contentType: String,
55 | content: ByteArray)
56 | {
57 | val outStream = getOutputStream()!!
58 | val out = BufferedOutputStream(outStream)
59 |
60 | val header = array(status,
61 | "Server: Kotlin HTTP Server 1.0",
62 | "Date: " + Date(),
63 | "Content-type: " + contentType,
64 | "Content-length: " + content.size)
65 | .makeString(separator = lineSeparator, postfix = lineSeparator + lineSeparator)
66 | .getBytes()
67 |
68 | out.write(header);
69 | out.flush()
70 |
71 | out.write(content)
72 | out.flush()
73 |
74 | outStream.close()
75 | }
76 |
77 |
78 | private fun Socket.sendHtmlResponse(status: String,
79 | title : String,
80 | body : String)
81 | {
82 | val html =
83 | """
84 | $title
85 |
86 | $body
87 |
88 | """
89 |
90 | this.sendHttpResponse(status, "text/html", html.toByteArray("UTF-8"))
91 | }
92 |
93 | fun Socket.sendFile(file: File, method: String, isRetry: Boolean = false) {
94 | val isDir = file.isDirectory()
95 |
96 | if (isDir && !isRetry)
97 | {
98 | sendFile(file = File(file.path + File.separator + DEFAULT_FILE),
99 | method = method,
100 | isRetry = true)
101 | return
102 | }
103 |
104 | if (file.exists() && !isDir)
105 | {
106 | val content = if (method == "GET") file.readBytes() else ByteArray(0)
107 | val contentType = fileExtToContentType(file.extension)
108 |
109 | sendHttpResponse(
110 | status = "HTTP/1.0 200 OK",
111 | contentType = contentType,
112 | content = content)
113 |
114 | System.out.println("File " + file.path + " of type " + contentType + " returned.")
115 | }
116 | else
117 | {
118 | sendHtmlResponse(
119 | status = "HTTP/1.0 404 Not Found",
120 | title = "File Not Found",
121 | body = "404 File Not Found: " + file.getPath() + "
")
122 |
123 | System.out.println("404 File Not Found: " + file)
124 | }
125 | }
126 |
127 | private fun fileExtToContentType(extension : String) : String = when {
128 | extension == "htm" || extension == "html" -> "text/html"
129 | extension == "gif" -> "image/gif"
130 | extension == "jpg" || extension == "jpeg" -> "image/jpeg"
131 | extension =="class" || extension == "jar" -> "applicaton/octet-stream"
132 | else -> "text/plain"
133 | }
134 | }
135 |
136 | fun main(args : Array)
137 | {
138 | val PORT : Int = 8080
139 |
140 | val serverConnect = ServerSocket(PORT)
141 |
142 | System.out.println("\nListening for connections on port " + PORT + "...\n")
143 |
144 | while (true)
145 | {
146 | val socket = serverConnect.accept()
147 | val thread = Thread(HttpServer(socket))
148 | thread.start()
149 | }
150 | }
--------------------------------------------------------------------------------
/kotlin-http-server/KotlinHTTPServer/src/HTTPServer2.kt:
--------------------------------------------------------------------------------
1 | package httpServer2
2 | /**
3 | * Created with IntelliJ IDEA.
4 | * User: maples
5 | * Date: 15/01/2013
6 | * Time: 12:49
7 | */
8 | import java.io.*
9 | import java.net.*
10 | import java.util.StringTokenizer
11 | import java.util.Date
12 | import java.util.concurrent.Executors
13 |
14 | fun main(args : Array)
15 | {
16 | val PORT : Int = 8080
17 |
18 | val serverConnect = ServerSocket(PORT)
19 |
20 | System.out.println("\nListening for connections on port " + PORT + "...\n")
21 |
22 | val pool = Executors.newCachedThreadPool()
23 |
24 | while (true)
25 | {
26 | val socket = serverConnect.accept()
27 | pool.execute(runnable { process(socket) })
28 | }
29 | }
30 |
31 | val WEB_ROOT : File = File(".")
32 | val DEFAULT_FILE : String = "index.html"
33 | val lineSeparator = System.getProperty("line.separator")!!;
34 |
35 | fun process(connect: Socket) : Unit {
36 | System.out.println("Connection opened. (" + Date() + ")")
37 |
38 | val input = BufferedReader(InputStreamReader(connect.getInputStream()!!))
39 |
40 | input use
41 | {
42 | val requestLine = input.readLine()
43 | if (requestLine != null)
44 | {
45 | val parse : StringTokenizer = StringTokenizer(requestLine)
46 | val method : String = parse.nextToken().toUpperCase()
47 |
48 | if (method != "GET" && method != "HEAD")
49 | {
50 | connect.sendHtmlResponse(
51 | status = "HTTP/1.1 501 Not Implemented",
52 | title = "Not Implemented",
53 | body = "501 Not Implemented: " + method + " method.
")
54 |
55 | System.out.println("501 Not Implemented: " + method + " method.")
56 | }
57 | else
58 | {
59 | val fileRequested = URLDecoder.decode(parse.nextToken(), "UTF-8")
60 | connect.sendFile(File(WEB_ROOT, fileRequested), method)
61 | }
62 | }
63 | }
64 |
65 | System.out.println("Connection closed.\n")
66 | }
67 |
68 | fun Socket.sendHttpResponse(status: String,
69 | contentType: String,
70 | content: ByteArray)
71 | {
72 | val outStream = getOutputStream()!!
73 | val out = BufferedOutputStream(outStream)
74 |
75 | val header = array(status,
76 | "Server: Kotlin HTTP Server 1.0",
77 | "Date: " + Date(),
78 | "Content-type: " + contentType,
79 | "Content-length: " + content.size)
80 | .makeString(separator = lineSeparator, postfix = lineSeparator + lineSeparator)
81 | .getBytes()
82 |
83 | out.write(header);
84 | out.flush()
85 |
86 | out.write(content)
87 | out.flush()
88 |
89 | outStream.close()
90 | }
91 |
92 |
93 | private fun Socket.sendHtmlResponse(status: String,
94 | title : String,
95 | body : String)
96 | {
97 | val html =
98 | """
99 | $title
100 |
101 | $body
102 |
103 | """
104 |
105 | this.sendHttpResponse(status, "text/html", html.toByteArray("UTF-8"))
106 | }
107 |
108 | fun Socket.sendFile(file: File, method: String, isRetry: Boolean = false) {
109 | val isDir = file.isDirectory()
110 |
111 | if (isDir && !isRetry)
112 | {
113 | sendFile(file = File(file.path + File.separator + DEFAULT_FILE),
114 | method = method,
115 | isRetry = true)
116 | return
117 | }
118 |
119 | if (file.exists() && !isDir)
120 | {
121 | val content = if (method == "GET") file.readBytes() else ByteArray(0)
122 | val contentType = fileExtToContentType(file.extension)
123 |
124 | sendHttpResponse(
125 | status = "HTTP/1.0 200 OK",
126 | contentType = contentType,
127 | content = content)
128 |
129 | System.out.println("File " + file.path + " of type " + contentType + " returned.")
130 | }
131 | else
132 | {
133 | sendHtmlResponse(
134 | status = "HTTP/1.0 404 Not Found",
135 | title = "File Not Found",
136 | body = "404 File Not Found: " + file.getPath() + "
")
137 |
138 | System.out.println("404 File Not Found: " + file)
139 | }
140 | }
141 |
142 | fun fileExtToContentType(extension : String) : String = when {
143 | extension == "htm" || extension == "html" -> "text/html"
144 | extension == "gif" -> "image/gif"
145 | extension == "jpg" || extension == "jpeg" -> "image/jpeg"
146 | extension =="class" || extension == "jar" -> "applicaton/octet-stream"
147 | else -> "text/plain"
148 | }
--------------------------------------------------------------------------------
/kotlin-http-server/KotlinHTTPServer/src/index.html:
--------------------------------------------------------------------------------
1 | This is the index.html file!
--------------------------------------------------------------------------------
/scala-http-server/README.textile:
--------------------------------------------------------------------------------
1 | h1. Scala HTTP Server Example
2 |
3 | Simple example demonstrating some Scala features.
4 |
--------------------------------------------------------------------------------
/scala-http-server/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Welcome!
6 |
7 |
8 | Welcome to Scala HTTP Server Example
9 |
10 |
--------------------------------------------------------------------------------
/scala-http-server/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.zeroturnaround.rebellabs
5 | scala-http-server-example
6 | 1.0
7 |
8 | 2.10.0
9 | UTF-8
10 |
11 |
12 |
13 | org.scala-lang
14 | scala-library
15 | ${scala.version}
16 |
17 |
18 |
19 | src/main/scala
20 |
21 |
22 | org.scala-tools
23 | maven-scala-plugin
24 | 2.15.2
25 |
26 |
27 |
28 | compile
29 | testCompile
30 |
31 |
32 |
33 |
34 | ${scala.version}
35 |
36 |
37 |
38 | maven-compiler-plugin
39 | 2.3.2
40 |
41 | 1.6
42 | 1.6
43 | UTF-8
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/scala-http-server/src/main/scala/org/zeroturnaround/HttpServer.scala:
--------------------------------------------------------------------------------
1 | package org.zeroturnaround
2 |
3 | import java.io._
4 | import java.net._
5 | import java.util._
6 |
7 | object HttpServer {
8 |
9 | val Encoding = "UTF-8"
10 | val WebRoot = new File(".")
11 | val DefaultFile = "index.html"
12 | val LineSep = System.getProperty("line.separator")
13 |
14 | case class Status(code: Int, text: String)
15 |
16 | def main(args: Array[String]) {
17 | val port = 8080
18 | val serverSocket = new ServerSocket(port)
19 | println(s"\nListening for connections on port ${port}...\n")
20 |
21 | val pool = concurrent.Executors.newCachedThreadPool()
22 |
23 | while(true)
24 | pool.execute(new HttpServer(serverSocket.accept()))
25 | }
26 |
27 | }
28 |
29 | class HttpServer(socket: Socket) extends Runnable {
30 |
31 | import HttpServer._ // import statics from companion object
32 |
33 | def run() {
34 | println(s"Connection opened. (${new Date()})")
35 |
36 | val source = io.Source.fromInputStream(socket.getInputStream(), Encoding)
37 | try {
38 | val line = source.getLines.next
39 | val tokens = new StringTokenizer(line)
40 |
41 | tokens.nextToken.toUpperCase match {
42 | case method @ ("GET" | "HEAD") =>
43 | val path = URLDecoder.decode(tokens.nextToken(), Encoding)
44 | sendFile(path, method)
45 |
46 | case method =>
47 | respondWithHtml(
48 | Status(501, "Not Implemented"),
49 | title = "501 Not Implemented",
50 | body = 501 Not Implemented: { method } method
51 | )
52 | println(s"501 Not Implemented: ${method} method.")
53 | }
54 | } finally
55 | source.close()
56 |
57 | }
58 |
59 | def respond(status: Status, contentType: String = "text/html", content: Array[Byte]) {
60 | val out = new BufferedOutputStream(socket.getOutputStream())
61 |
62 | val header = s"""
63 | |HTTP/1.1 ${status.code} ${status.text}
64 | |Server: Scala HTTP Server 1.0
65 | |Date: ${new Date()}
66 | |Content-type: ${contentType}
67 | |Content-length: ${content.length}
68 | """.trim.stripMargin + LineSep + LineSep
69 |
70 | try {
71 | out.write(header.getBytes(Encoding))
72 | out.flush()
73 |
74 | out.write(content)
75 | out.flush()
76 | } finally {
77 | out.close()
78 | }
79 | }
80 |
81 | def respondWithHtml(status: Status, title: String, body: xml.NodeSeq) =
82 | respond(
83 | status = status,
84 | content = xml.Xhtml.toXhtml(
85 |
86 | { title }
87 |
88 | { body }
89 |
90 |
91 | ).getBytes(Encoding)
92 | )
93 |
94 | def sendFile(path: String, method: String) = toFile(path) match {
95 | case Some(file) =>
96 | val content = if ("GET" == method) {
97 | val bytesOut = new ByteArrayOutputStream()
98 | sys.process.BasicIO.transferFully(new FileInputStream(file), bytesOut)
99 | bytesOut.toByteArray()
100 | } else
101 | Array.emptyByteArray
102 | val contentType = {
103 | val fileExt = file.getName.split('.').lastOption getOrElse ""
104 | getContentType(fileExt)
105 | }
106 | respond(
107 | Status(200, "OK"),
108 | contentType,
109 | content
110 | )
111 | println(s"File ${file.getPath} of type ${contentType} returned.")
112 | case None =>
113 | respondWithHtml(
114 | Status(404, "Not Found"),
115 | title = "404 File Not Found",
116 | body = 404 File Not Found: {path}
117 | )
118 | println(s"404 File Not Found: ${path}")
119 | }
120 |
121 | def toFile(path: String): Option[File] =
122 | if (path contains "..") {
123 | respondWithHtml(
124 | Status(403, "Forbidden"),
125 | title = "403 Forbidden",
126 | body = 403 Forbidden: .. in path not allowed: {path}
127 | )
128 | println(s"403 Forbidden: .. in path not allowed: ${path}")
129 | throw new SecurityException(s".. in path not allowed: ${path}")
130 | } else
131 | toFile(new File(WebRoot, path))
132 |
133 | def toFile(file: File, isRetry: Boolean = false): Option[File] =
134 | if (file.isDirectory && !isRetry)
135 | toFile(new File(file, DefaultFile), true)
136 | else if (file.isFile)
137 | Some(file)
138 | else
139 | None
140 |
141 | def getContentType(extension: String) = extension match {
142 | case "htm" | "html" => "text/html"
143 | case "gif" => "image/gif"
144 | case "jpg" | "jpeg" => "image/jpeg"
145 | case "class" | "jar" => "applicaton/octet-stream"
146 | case _ => "text/plain"
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/xtend-http-server/src/com/zt/HttpServer.xtend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zeroturnaround/jvm-languages-report/0c2f644f91f3ef0ab25be35ae201a57eec606090/xtend-http-server/src/com/zt/HttpServer.xtend
--------------------------------------------------------------------------------
/xtend-http-server/src/index.html:
--------------------------------------------------------------------------------
1 | This is the index.html file!
--------------------------------------------------------------------------------
/xtend-http-server/xtend-gen/com/zt/HttpServer.java:
--------------------------------------------------------------------------------
1 | package com.zt;
2 |
3 | import java.io.BufferedOutputStream;
4 | import java.io.BufferedReader;
5 | import java.io.File;
6 | import java.io.InputStream;
7 | import java.io.InputStreamReader;
8 | import java.io.OutputStream;
9 | import java.io.PrintWriter;
10 | import java.net.ServerSocket;
11 | import java.net.Socket;
12 | import java.util.ArrayList;
13 | import java.util.Date;
14 | import java.util.List;
15 | import java.util.StringTokenizer;
16 | import org.apache.commons.io.FileUtils;
17 | import org.eclipse.xtend2.lib.StringConcatenation;
18 | import org.eclipse.xtext.xbase.lib.CollectionLiterals;
19 | import org.eclipse.xtext.xbase.lib.Conversions;
20 | import org.eclipse.xtext.xbase.lib.Exceptions;
21 | import org.eclipse.xtext.xbase.lib.InputOutput;
22 | import org.eclipse.xtext.xbase.lib.ObjectExtensions;
23 |
24 | @SuppressWarnings("all")
25 | public class HttpServer implements Runnable {
26 | private final String WEB_ROOT = ".";
27 |
28 | private final String DEFAULT_FILE = "index.html";
29 |
30 | private final Socket socket;
31 |
32 | public HttpServer(final Socket socket) {
33 | this.socket = socket;
34 | }
35 |
36 | public static void main(final String[] args) {
37 | try {
38 | final int PORT = 8080;
39 | ServerSocket _serverSocket = new ServerSocket(PORT);
40 | final ServerSocket serverConnect = _serverSocket;
41 | String _plus = ("\nListening for connections on port " + Integer.valueOf(PORT));
42 | String _plus_1 = (_plus + "...\n");
43 | InputOutput.println(_plus_1);
44 | boolean _while = true;
45 | while (_while) {
46 | {
47 | final Socket socket = serverConnect.accept();
48 | HttpServer _httpServer = new HttpServer(socket);
49 | Thread _thread = new Thread(_httpServer);
50 | final Thread thread = _thread;
51 | thread.start();
52 | }
53 | _while = true;
54 | }
55 | } catch (Exception _e) {
56 | throw Exceptions.sneakyThrow(_e);
57 | }
58 | }
59 |
60 | public void run() {
61 | try {
62 | Date _date = new Date();
63 | String _plus = ("Connection opened. (" + _date);
64 | String _plus_1 = (_plus + ")");
65 | InputOutput.println(_plus_1);
66 | InputStream _inputStream = this.socket.getInputStream();
67 | InputStreamReader _inputStreamReader = new InputStreamReader(_inputStream);
68 | BufferedReader _bufferedReader = new BufferedReader(_inputStreamReader);
69 | final BufferedReader input = _bufferedReader;
70 | final String requestLine = input.readLine();
71 | boolean _notEquals = ObjectExtensions.operator_notEquals(requestLine, null);
72 | if (_notEquals) {
73 | StringTokenizer _stringTokenizer = new StringTokenizer(requestLine);
74 | final StringTokenizer parse = _stringTokenizer;
75 | String _nextToken = parse.nextToken();
76 | final String method = _nextToken.toUpperCase();
77 | boolean _and = false;
78 | boolean _notEquals_1 = ObjectExtensions.operator_notEquals(method, "GET");
79 | if (!_notEquals_1) {
80 | _and = false;
81 | } else {
82 | boolean _notEquals_2 = ObjectExtensions.operator_notEquals(method, "HEAD");
83 | _and = (_notEquals_1 && _notEquals_2);
84 | }
85 | if (_and) {
86 | String _plus_2 = ("501 Not Implemented: " + method);
87 | String _plus_3 = (_plus_2 + " method.
");
88 | this.sendHtmlResponse(this.socket,
89 | "HTTP/1.1 501 Not Implemented",
90 | "Not Implemented", _plus_3);
91 | String _plus_4 = ("501 Not Implemented: " + method);
92 | String _plus_5 = (_plus_4 + " method.");
93 | InputOutput.println(_plus_5);
94 | } else {
95 | String _nextToken_1 = parse.nextToken();
96 | File _file = new File(this.WEB_ROOT, _nextToken_1);
97 | this.sendFile(this.socket, _file, method, false);
98 | }
99 | }
100 | InputOutput.println("Connection closed.\n");
101 | } catch (Exception _e) {
102 | throw Exceptions.sneakyThrow(_e);
103 | }
104 | }
105 |
106 | public void sendHttpResponse(final Socket socket, final String status, final String contentType, final byte[] content) {
107 | try {
108 | final OutputStream outStream = socket.getOutputStream();
109 | BufferedOutputStream _bufferedOutputStream = new BufferedOutputStream(outStream);
110 | final BufferedOutputStream out = _bufferedOutputStream;
111 | PrintWriter _printWriter = new PrintWriter(out);
112 | final PrintWriter printOut = _printWriter;
113 | printOut.println(status);
114 | printOut.println("Server: Xtend HTTP Server 1.0");
115 | Date _date = new Date();
116 | String _plus = ("Date: " + _date);
117 | printOut.println(_plus);
118 | String _plus_1 = ("Content-type: " + contentType);
119 | printOut.println(_plus_1);
120 | int _size = ((List)Conversions.doWrapArray(content)).size();
121 | String _plus_2 = ("Content-length: " + Integer.valueOf(_size));
122 | printOut.println(_plus_2);
123 | printOut.println();
124 | printOut.flush();
125 | out.write(content);
126 | out.flush();
127 | outStream.close();
128 | } catch (Exception _e) {
129 | throw Exceptions.sneakyThrow(_e);
130 | }
131 | }
132 |
133 | public void sendHtmlResponse(final Socket socket, final String status, final String title, final String body) {
134 | try {
135 | StringConcatenation _builder = new StringConcatenation();
136 | _builder.append("");
137 | _builder.newLine();
138 | _builder.append(" ");
139 | _builder.append("");
140 | _builder.append(title, " ");
141 | _builder.append("");
142 | _builder.newLineIfNotEmpty();
143 | _builder.append(" ");
144 | _builder.append("");
145 | _builder.newLine();
146 | _builder.append(" ");
147 | _builder.append(body, " ");
148 | _builder.newLineIfNotEmpty();
149 | _builder.append(" ");
150 | _builder.append("");
151 | _builder.newLine();
152 | _builder.append("");
153 | final CharSequence html = _builder;
154 | String _string = html.toString();
155 | byte[] _bytes = _string.getBytes("UTF-8");
156 | this.sendHttpResponse(socket, status, "text/html", _bytes);
157 | } catch (Exception _e) {
158 | throw Exceptions.sneakyThrow(_e);
159 | }
160 | }
161 |
162 | public String getFileExtension(final File file) {
163 | String _name = file.getName();
164 | final int dotPosition = _name.lastIndexOf(".");
165 | String _name_1 = file.getName();
166 | int _plus = (dotPosition + 1);
167 | return _name_1.substring(_plus);
168 | }
169 |
170 | public String sendFile(final Socket socket, final File file, final String method, final boolean isRetry) {
171 | String _xblockexpression = null;
172 | {
173 | final boolean isDir = file.isDirectory();
174 | boolean _and = false;
175 | if (!isDir) {
176 | _and = false;
177 | } else {
178 | boolean _not = (!isRetry);
179 | _and = (isDir && _not);
180 | }
181 | if (_and) {
182 | String _path = file.getPath();
183 | String _plus = (_path + File.separator);
184 | String _plus_1 = (_plus + this.DEFAULT_FILE);
185 | File _file = new File(_plus_1);
186 | this.sendFile(socket, _file, method, true);
187 | return null;
188 | }
189 | String _xifexpression = null;
190 | boolean _and_1 = false;
191 | boolean _exists = file.exists();
192 | if (!_exists) {
193 | _and_1 = false;
194 | } else {
195 | boolean _not_1 = (!isDir);
196 | _and_1 = (_exists && _not_1);
197 | }
198 | if (_and_1) {
199 | String _xblockexpression_1 = null;
200 | {
201 | byte[] _xifexpression_1 = null;
202 | boolean _equals = ObjectExtensions.operator_equals(method, "GET");
203 | if (_equals) {
204 | byte[] _readBytes = this.readBytes(file);
205 | _xifexpression_1 = _readBytes;
206 | } else {
207 | ArrayList