2010-11-12 10 views
10

Il seguente è possibile utilizzando Python:Inizializzare un web server in Scala

$ apt-get install python 
$ easy_install Flask 
$ cat > hello.py 
from flask import Flask 
app = Flask(__name__) 

@app.route("/") 
def hello(): 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 
$ python hello.py 

4 comandi e 7 righe di codice per ottenere un web server in esecuzione è davvero molto impressionante.

Qual è l'equivalente Scala?

+3

Vuol dire 4 comandi in un sistema in cui esiste apt-get, easy_install viene fornito con pitone e utilizzando una shell sh. Pensi di avere anche l'accesso alla root? – huynhjl

+8

Sì, presumo anche che il sistema abbia CPU, RAM, storage, un sistema operativo installato, una tastiera e un display;) – Matthew

+3

Questa è una domanda seria, o solo un tentativo di mostrare quanto sia interessante Python + Flask ? Quante volte è necessario configurare un server Web prima di dover digitare, ad esempio, 15 comandi anziché 4 è il passo limitante della velocità nel lavoro? Concedo che questo è molto bello, ma l'unica applicazione che riesco a pensare in cima alla mia testa dove ciò è richiesto invece che semplicemente divertente è incorporare un exploit in un piccolo buffer che converte una macchina target in un server web. –

risposta

4

Bene, c'è Scalatra, che mira ad essere analogo a Sinatra di Ruby in termini di funzionalità e facilità d'uso.

10

Potresti trovare Unfiltered degno un'occhiata.

+0

Il collegamento è rotto. – Meglio

+0

Ho aggiornato il collegamento. –

+0

Il collegamento è stato interrotto di nuovo ... –

10

so Max alread mentioned, ma non ho potuto resistere sottolineando Scalatra's 6 linee ciao mondo:

import org.scalatra._ 

class ScalatraExample extends ScalatraServlet { 
    get("/") { 
    <h1>Hello, world!</h1> 
    } 
} 

In ogni caso, dare un'occhiata a disposizione Scala web frameworks.

EDIT

C'è qualche discussione su quanto facile è quello di ottenere il utensili pronto, con particolare riguardo per il sollevamento. Quindi, ecco una sessione su Ubuntu. La maggior parte del mio tempo è stata spesa cercando di capire dove si trovava Sun's Java nel gestore dei pacchetti. In ogni caso, una volta che Java è stato installato, questo è come è andata, con tutti i messaggi eliso, così si può vedere quello che ho dovuto digitare:

[email protected]:~$ wget -q -O bin/sbt-launch.jar http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.4.jar 
[email protected]:~$ echo 'java -Xmx512M -jar `dirname $0`/sbt-launch.jar "[email protected]"' > bin/sbt 
[email protected]:~$ chmod u+x bin/sbt 
[email protected]:~$ mkdir app 
[email protected]:~$ cd app 
[email protected]:~/app$ sbt 
Project does not exist, create new project? (y/N/s) s 
> *lifty is org.lifty lifty 1.4 
> lifty create project-blank sample 2.1 
> reload 
> update 
> jetty-run 

Lì, web server in esecuzione. Ovviamente, devi sapere in anticipo SBT e Lifty, per sapere anche che li useresti per far funzionare un programma Scala Lift, ma, d'altra parte, non avevo mai sentito parlare di Flask, quindi spenderei sicuramente più tempo a cercare di capire come ottenere un'applicazione di server web in Python piuttosto che ottenere un Lift One.

Anche io non ho capito bene al primo tentativo - ho provato ad andare su Scala 2.8.1 (il precedente usa una versione 2.7.7 predefinita, anche se funzionerà anche 2.8.0), solo per scoprire che non esiste ancora una versione di Lift disponibile per quella versione di Scala. D'altra parte, avevo già installato lifty e l'ho disinstallato solo per mostrare il comando che lo installa.

Vorrei che ci fosse un pacchetto Debian/Ubuntu per SBT - è solo un piccolo script di shell e un file jar, dopotutto, e si occupa di scaricare Scala, Lift, ecc. E di qualsiasi versione di cui avete bisogno .

È un modello diverso da Python e Ruby, in cui il linguaggio viene fornito con un gestore di pacchetti che gestisce la maggior parte delle cose.

+0

Grazie, 6 linee di Scala sono fantastiche! C'è un modo per installare Scala e Scalatra e avviare il server con pochi comandi? – Matthew

+0

Vedere "Quick start Scalatra": http://blog.everythings-beta.com/?p=430. Questo sorvolo sulla fase di installazione di sbt, ma non è difficile. Ovviamente, sarebbe un vantaggio avere un pacchetto debian/ubuntu per questo. –

+0

@ Matthew sicuro. Avvio rapido sulla pagina Web di Scalatra è molto breve. Hai solo bisogno di installare git e sbt. Vorrei che implementassero un processore come Lifty (https://github.com/Lifty/Lifty), in modo tale che sbt fosse sufficiente. –

1

È possibile usare un molo Server incorporato:

/* 
* Required Libs: Jetty, Servlet API 
* 
* Compile: 
* scalac -cp jetty-6.1.14.jar:jetty-util-6.1.14.jar:servlet-api-2.5-6.1.14.jar WebServer.scala 
* 
* Run: 
* scala -cp .:jetty-6.1.14.jar:jetty-util-6.1.14.jar:servlet-api-2.5-6.1.14.jar WebServer 
*/ 
import org.mortbay.jetty.Server 
import org.mortbay.jetty.servlet.Context 
import javax.servlet.http.{HttpServlet, 
         HttpServletRequest, 
         HttpServletResponse} 

class HelloServlet extends HttpServlet { 
    override def doGet(req : HttpServletRequest, resp : HttpServletResponse) = 
    resp.getWriter().print("Hello There!") 
} 

object WebServer { 
    def main(args: Array[String]) { 
    val server = new Server(8080) 
    val root = new Context(server, "/", Context.SESSIONS) 
    root.addServlet(classOf[HelloServlet], "/*") 
    server.start() 

    println("Point your browser to http://localhost:8080/") 
    println("Type [CTRL]+[C] to quit!") 

    Thread.sleep(Long.MaxValue) 
    } 
} 

Nel caso in cui si target per un confronto LOC, si utilizza il server HTTP integrato con il Sun JDK. Un'altra soluzione potrebbe essere l'uso di javax.xml.ws.Endpoint e dell'API del provider.

2

Questa soluzione utilizza un JAX-WS Endpoint:

import java.io._ 
import javax.xml.ws._ 
import javax.xml.ws.http._ 
import javax.xml.transform._ 
import javax.xml.transform.stream._ 

@WebServiceProvider 
@ServiceMode(value=Service.Mode.PAYLOAD) 
class P extends Provider[Source] { 
    def invoke(source: Source) = new StreamSource(new StringReader("<p>Hello There!</p>")); 
} 

val address = "http://127.0.0.1:8080/" 
Endpoint.create(HTTPBinding.HTTP_BINDING, new P()).publish(address) 

println("Service running at "+address) 
println("Type [CTRL]+[C] to quit!") 

Thread.sleep(Long.MaxValue) 

è possibile copiarlo in un file WebServer.Scala ed eseguirlo semplicemente digitando:

scala WebServer.scala 
11

Questo utilizza la classe HTTPServer che è costruito nella JDK6. Sentiti libero di suggerire miglioramenti, sono nuovo di Scala.

package org.test.simplehttpserver 

import java.net.InetSocketAddress 
import com.sun.net.httpserver.{HttpExchange, HttpHandler, HttpServer} 
import collection.mutable.HashMap 

abstract class SimpleHttpServerBase(val socketAddress: String = "127.0.0.1", 
            val port: Int = 8080, 
            val backlog: Int = 0) extends HttpHandler { 
    private val address = new InetSocketAddress(socketAddress, port) 
    private val server = HttpServer.create(address, backlog) 
    server.createContext("/", this) 

    def redirect(url: String) = 
    <html> 
     <head> 
      <meta http-equiv="Refresh" content={"0," + url}/> 
     </head> 
     <body> 
     You are being redirected to: 
     <a href={url}> 
      {url} 
     </a> 
     </body> 
    </html> 

    def respond(exchange: HttpExchange, code: Int = 200, body: String = "") { 
    val bytes = body.getBytes 
    exchange.sendResponseHeaders(code, bytes.size) 
    exchange.getResponseBody.write(bytes) 
    exchange.getResponseBody.write("\r\n\r\n".getBytes) 
    exchange.getResponseBody.close() 
    exchange.close() 
    } 

    def start() = server.start() 

    def stop(delay: Int = 1) = server.stop(delay) 
} 

abstract class SimpleHttpServer extends SimpleHttpServerBase { 
    private val mappings = new HashMap[String,() => Any] 

    def get(path: String)(action: => Any) = mappings += path -> (() => action) 

    def handle(exchange: HttpExchange) = mappings.get(exchange.getRequestURI.getPath) match { 
    case None => respond(exchange, 404) 
    case Some(action) => try { 
     respond(exchange, 200, action().toString) 
    } catch { 
     case ex: Exception => respond(exchange, 500, ex.toString) 
    } 
    } 
} 

class HelloApp extends SimpleHttpServer { 
    var count = 0 

    get("/") { 
    "There's nothing here" 
    } 

    get("/hello") { 
    "Hello, world!" 
    } 

    get("/markup") { 
    <html> 
     <head> 
     <title>Test Title</title> 
     </head> 
     <body> 
     Test Body 
     </body> 
    </html> 
    } 

    def countPage = <html> 
    <head> 
     <title>Test Title</title> 
    </head> 
    <body> 
     Count: 
     {count}<a href="/increaseCount">++</a> 
     <a href="/decreaseCount">--</a> 
     <a href="/resetCount">Reset</a> 
    </body> 
    </html> 

    get("/count") { 
    countPage 
    } 

    get("/resetCount") { 
    count = 0 
    redirect("/count") 
    } 

    get("/increaseCount") { 
    count = count + 1 
    redirect("/count") 
    } 

    get("/decreaseCount") { 
    count = count - 1 
    redirect("/count") 
    } 

    get("/error") { 
    throw new RuntimeException("Bad bad error occurred") 
    } 
} 

object Main { 

    def main(args: Array[String]) { 
    val server = new HelloApp() 
    server.start() 
    } 
} 
+0

Esiste un modo per specificare il tipo di contenuto per la risposta, ad esempio, con l'immagine? – Tutankhamen

+1

Impostare il tipo di contenuto utilizzando una chiamata a exchange.sendResponseHeaders(). – Tommy

+0

Grazie, già fatto :) – Tutankhamen

1

Scala equivalente è in 6 comandi:

$ curl https://raw.github.com/n8han/conscript/master/setup.sh | sh 
$ ~/bin/cs n8han/giter8 
$ ~/bin/g8 scalatra/scalatra-sbt --name=scalatra-example 
$ cd scalatra-example 
$ wget http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-tools.sbt/sbt-launch/0.11.0/sbt-launch.jar 
$ java -Xmx512M -jar sbt-launch.jar ~jetty-run 

Utilizzo della riproduzione,

step #1 download Play, then 
$ play install scala 
$ play new myproject --with scala 
$ play run myproject 
0

Come David Winslow accennato, il codice Unfiltered utilizzo frammento di

INFO: semplice funzionalità API per Apache Spark esempio di conteggio delle parole scritto in Scala u canta Unfiltered.

object SimplePlan extends Plan { 
    def intent = { 
    case req @ GET(Path("/get")) => { 
    Ok ~> ResponseString(WordCount.count("Test #1: Test the Default word count program").mkString("\n")); 
    } 

    case req @ POST(Path("/get_custom")) => { 
    val custom_string = Body.string(req) 
    Ok ~> ResponseString(WordCount.count(custom_string).mkString("\n")) 
    } 
} 
} 

object SimpleServer extends App { 
    val bindingIP = SocketPortBinding(host = "localhost", port = 8080) 
    unfiltered.jetty.Server.portBinding(bindingIP).plan(SimplePlan).run() 
} 

Esempio completo è here