2010-11-12 16 views
10

Poniżej jest możliwe przy użyciu Pythona:ładującego serwer WWW w 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 polecenia i 7 linii kodu, aby uzyskać uruchomiony serwer WWW jest rzeczywiście imponująca.

Co to jest odpowiednik Scala?

+3

To znaczy, 4 polecenia na systemie, w którym istnieje apt-get, easy_install jest w zestawie z python i przy użyciu powłoki sh. Czy zakładasz też dostęp do roota? – huynhjl

+8

Tak, zakładam również, że system ma procesor, pamięć RAM, pamięć masową, zainstalowany system operacyjny, klawiaturę i wyświetlacz;) – Matthew

+3

Czy jest to poważne pytanie, czy tylko próba pokazania, jak fajna jest Python + Flask ? Ile razy trzeba skonfigurować serwer WWW przed koniecznością wpisywania, powiedzmy, 15 poleceń zamiast 4 jest krokiem ograniczającym szybkość w swojej pracy? Uznaję, że jest to bardzo fajne, ale jedyną aplikacją, o której mogę pomyśleć z góry, gdzie jest to wymagane, a nie tylko zabawne, jest osadzenie exploita w małym buforze, który konwertuje komputer docelowy na serwer WWW. –

Odpowiedz

4

Cóż, jest Scalatra, który ma być analogiczny do Sinatry Ruby pod względem funkcjonalności i łatwości użytkowania.

10

Warto odszukać Unfiltered.

+0

Link jest uszkodzony. – Meglio

+0

Zaktualizowałem link. –

+0

Łącze jest zepsute ponownie ... –

10

wiem Max alread mentioned, ale nie mogłem się oprzeć wskazując Scalatra's 6 linii Hello World:

import org.scalatra._ 

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

Zresztą spójrz na dostępnej Scala web frameworks.

EDIT

Jest jakaś dyskusja o tym, jak łatwo jest dostać oprzyrządowania gotowy, szczególnie w odniesieniu do windy. Oto sesja na temat Ubuntu. Większość czasu spędziłem próbując dowiedzieć się, gdzie działa Java Sun w menedżerze pakietów. W każdym razie, gdy została zainstalowana Java, to jak to poszło, ze wszystkie komunikaty pomijana, więc można zobaczyć, co tak naprawdę musiał wpisać:

[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 

Tam, bieganie serwera WWW. Oczywiście, musisz wcześniej wiedzieć o SBT i Lifty, aby wiedzieć, że użyjesz ich do uruchomienia programu Scala Lift, ale z drugiej strony, nigdy nie słyszałem o Flasku, więc z pewnością spędziłbym czas więcej czasu na zastanowienie się, jak uruchomić aplikację serwera WWW w Pythonie, niż otrzymałem podnośnik.

Ja też nie udało mi się uzyskać tego przy pierwszej próbie - próbowałem przejść do Scala 2.8.1 (powyższa wersja używa domyślnej wersji 2.7.7, chociaż 2.8.0 też działa), tylko po to, aby się przekonać, że nie ma jeszcze wersji Lift dostępnej dla tej wersji Scala. Z drugiej strony, miałem już zainstalowany lifty i odinstalowałem go tylko po to, by pokazać komendę, która go instaluje.

Żałuję, że nie było pakietu Debian/Ubuntu dla SBT - w końcu jest to tylko mały skrypt powłoki i plik JAR, i dba o pobieranie Scala, Lift, itp. Iw dowolnej wersji, jakiej potrzebujesz .

Jest to inny model niż Python i Ruby, gdzie język pochodzi z menedżera pakietów, który obsługuje większość rzeczy.

+0

Dzięki, 6 linii Scala jest niesamowita! Czy istnieje sposób na zainstalowanie Scali i Scalatry i uruchomienie serwera za pomocą kilku poleceń? – Matthew

+0

Zobacz "Szybki start Scalatra": http://blog.everythings-beta.com/?p=430. To glosuje nad etapem instalowania sbt, ale nie jest to trudne. Oczywiście byłoby korzystne mieć pakiet debian/ubuntu. –

+0

@Matthew Sure. Szybki start na stronie internetowej Scalatry jest bardzo krótki. Potrzebujesz tylko git i sbt. Chciałbym, żeby wdrożyli taki procesor jak Lifty (https://github.com/Lifty/Lifty), więc wystarczyłoby sbt. –

1

Można użyć wbudowanego Jetty serwera:

/* 
* 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) 
    } 
} 

w przypadku, gdy celem dla porównania LOC, użyć wbudowanego serwera HTTP z Sun JDK. Innym rozwiązaniem może być użycie javax.xml.ws.Endpoint i Provider API.

2

Rozwiązanie to wykorzystuje JAX-WS punkt końcowy:

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) 

można skopiować go do pliku serwera WWW.scala i uruchomić go po prostu wpisując:

scala WebServer.scala 
11

ta wykorzystuje klasę HTTPServer, który jest wbudowany w JDK6. Zapraszam do sugerowania ulepszeń, jestem nowy w Scali.

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

Czy istnieje sposób na określenie typu zawartości dla odpowiedzi, na przykład z obrazem? – Tutankhamen

+1

Ustaw typ zawartości za pomocą wywołania metody exchange.sendResponseHeaders(). – Tommy

+0

Dzięki, już wykonane :) – Tutankhamen

1

równoważne Scala jest w 6 poleceń:

$ 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 

Korzystanie Play

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

Jak David Winslow wspomniano, kod Unfiltered Wykorzystanie fragment

INFO: Proste funkcje API dla Apache Spark przykład liczenia słów napisany w Scala u śpiewaj Niefiltrowane.

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() 
} 

Kompletna przykładem jest here