Skip to content

Latest commit

 

History

History
380 lines (304 loc) · 15.9 KB

README_de_DE.md

File metadata and controls

380 lines (304 loc) · 15.9 KB

Martini wercker statusGoDoc

Martini ist ein mächtiges Package zur schnellen Entwicklung von modularen Webanwendungen und -services in Golang.

Ein Projekt starten

Nach der Installation von Go und dem Einrichten des GOPATH, erstelle Deine erste .go-Datei. Speichere sie unter server.go.

package main

import "github.com/go-martini/martini"

func main() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hallo Welt!"
  })
  m.Run()
}

Installiere anschließend das Martini Package (Go 1.1 oder höher wird vorausgesetzt):

go get github.com/go-martini/martini

Starte den Server:

go run server.go

Der Martini-Webserver ist nun unter localhost:3000 erreichbar.

Hilfe

Abonniere den Emailverteiler

Schaue das Demovideo

Stelle Fragen auf Stackoverflow mit dem Martini-Tag

GoDoc Dokumentation

Eigenschaften

  • Sehr einfach nutzbar
  • Nicht-intrusives Design
  • Leicht kombinierbar mit anderen Golang Packages
  • Ausgezeichnetes Path Matching und Routing
  • Modulares Design - einfaches Hinzufügen und Entfernen von Funktionen
  • Eine Vielzahl von guten Handlern/Middlewares nutzbar
  • Großer Funktionsumfang mitgeliefert
  • Voll kompatibel mit dem http.HandlerFunc Interface.
  • Standardmäßiges Ausliefern von Dateien (z.B. von AngularJS-Apps im HTML5-Modus)

Mehr Middleware

Mehr Informationen zur Middleware und Funktionalität findest Du in den Repositories der martini-contrib Gruppe.

Inhaltsverzeichnis

Classic Martini

Einen schnellen Start in ein Projekt ermöglicht martini.Classic(), dessen Voreinstellungen sich für die meisten Webanwendungen eignen:

  m := martini.Classic()
  // ... Middleware und Routing hier einfügen
  m.Run()

Aufgelistet findest Du einige Aspekte, die martini.Classic() automatich berücksichtigt:

Handler

Handler sind das Herz und die Seele von Martini. Ein Handler ist grundsätzlich jede Art von aufrufbaren Funktionen:

m.Get("/", func() {
  println("Hallo Welt")
})

Rückgabewerte

Wenn ein Handler Rückgabewerte beinhaltet, übergibt Martini diese an den aktuellen http.ResponseWriter in Form eines String:

m.Get("/", func() string {
  return "Hallo Welt" // HTTP 200 : "Hallo Welt"
})

Die Rückgabe eines Statuscode ist optional:

m.Get("/", func() (int, string) {
  return 418, "Ich bin eine Teekanne" // HTTP 418 : "Ich bin eine Teekanne"
})

Service Injection

Handler werden per Reflection aufgerufen. Martini macht Gebrauch von Dependency Injection, um Abhängigkeiten in der Argumentliste von Handlern aufzulösen. Dies macht Martini komplett inkompatibel mit Golangs http.HandlerFunc Interface.

Fügst Du einem Handler ein Argument hinzu, sucht Martini in seiner Liste von Services und versucht, die Abhängigkeiten via Type Assertion aufzulösen.

m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res und req wurden von Martini injiziert
  res.WriteHeader(200) // HTTP 200
})

Die Folgenden Services sind Bestandteil von martini.Classic():

Routing

Eine Route ist in Martini eine HTTP-Methode gepaart mit einem URL-Matching-Pattern. Jede Route kann eine oder mehrere Handler-Methoden übernehmen:

m.Get("/", func() {
  // zeige etwas an
})

m.Patch("/", func() {
  // aktualisiere etwas
})

m.Post("/", func() {
  // erstelle etwas
})

m.Put("/", func() {
  // ersetze etwas
})

m.Delete("/", func() {
  // lösche etwas
})

m.Options("/", func() {
  // HTTP-Optionen
})

m.NotFound(func() {
  // bearbeite 404-Fehler
})

Routen werden in der Reihenfolge, in welcher sie definiert wurden, zugeordnet. Die bei einer Anfrage zuerst zugeordnete Route wird daraufhin aufgerufen.

Routenmuster enthalten ggf. benannte Parameter, die über den martini.Params Service abrufbar sind:

m.Get("/hello/:name", func(params martini.Params) string {
  return "Hallo " + params["name"]
})

Routen können mit Globs versehen werden:

m.Get("/hello/**", func(params martini.Params) string {
  return "Hallo " + params["_1"]
})

Reguläre Ausdrücke sind ebenfalls möglich:

m.Get("/hello/(?P<name>[a-zA-Z]+)", func(params martini.Params) string {
  return fmt.Sprintf ("Hallo %s", params["name"])
})

Weitere Informationen zum Syntax regulärer Ausdrücke findest Du in der Go Dokumentation.

Routen-Handler können auch ineinander verschachtelt werden. Dies ist bei der Authentifizierung und den Berechtigungen nützlich.

m.Get("/secret", authorize, func() {
  // wird ausgeführt, solange authorize nichts zurückgibt
})

Routengruppen können durch die Group-Methode hinzugefügt werden.

m.Group("/books", func(r martini.Router) {
    r.Get("/:id", GetBooks)
    r.Post("/new", NewBook)
    r.Put("/update/:id", UpdateBook)
    r.Delete("/delete/:id", DeleteBook)
})

Sowohl Handlern als auch Middlewares können Gruppen übergeben werden.

m.Group("/books", func(r martini.Router) {
    r.Get("/:id", GetBooks)
    r.Post("/new", NewBook)
    r.Put("/update/:id", UpdateBook)
    r.Delete("/delete/:id", DeleteBook)
}, MyMiddleware1, MyMiddleware2)

Services

Services sind Objekte, welche der Argumentliste von Handlern beigefügt werden können. Du kannst einem Service der Global oder Request Ebene zuordnen.

Global Mapping

Eine Martini-Instanz implementiert das inject.Injector Interface, sodass ein Service leicht zugeordnet werden kann:

db := &MyDatabase{}
m := martini.Classic()
m.Map(db) // der Service ist allen Handlern unter *MyDatabase verfügbar
// ...
m.Run()

Request-Level Mapping

Das Zuordnen auf der Request-Ebene kann in einem Handler via martini.Context realisiert werden:

func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
  logger := &MyCustomLogger{req}
  c.Map(logger) // zugeordnet als *MyCustomLogger
}

Werten einem Interface zuordnen

Einer der mächtigsten Aspekte von Services ist dessen Fähigkeit, einen Service einem Interface zuzuordnen. Möchtest Du den http.ResponseWriter mit einem Decorator (Objekt) und dessen Zusatzfunktionen überschreiben, definiere den Handler wie folgt:

func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
  rw := NewSpecialResponseWriter(res)
  c.MapTo(rw, (*http.ResponseWriter)(nil)) // überschribe ResponseWriter mit dem  ResponseWriter Decorator
}

Statische Dateien bereitstellen

Eine martini.Classic() Instanz übertragt automatisch statische Dateien aus dem "public"-Ordner im Stammverzeichnis Deines Servers. Dieses Verhalten lässt sich durch weitere martini.Static Handler auf andere Verzeichnisse übertragen.

m.Use(martini.Static("assets")) // überträgt auch vom "assets"-Verzeichnis

Eine voreingestelle Datei übertragen

Du kannst die URL zu einer lokalen Datei angeben, sollte die URL einer Anfrage nicht gefunden werden. Durch einen Präfix können bestimmte URLs ignoriert werden. Dies ist für Server nützlich, welche statische Dateien übertragen und ggf. zusätzliche Handler defineren (z.B. eine REST-API). Ist dies der Fall, so ist das Anlegen eines Handlers in der NotFound-Reihe nützlich.

Das gezeigte Beispiel zeigt die /index.html immer an, wenn die angefrage URL keiner lokalen Datei zugeordnet werden kann bzw. wenn sie nicht mit /api/v beginnt:

static := martini.Static("assets", martini.StaticOptions{Fallback: "/index.html", Exclude: "/api/v"})
m.NotFound(static, http.NotFound)

Middleware Handler

Middleware-Handler befinden sich logisch zwischen einer Anfrage via HTTP und dem Router. Im wesentlichen unterscheiden sie sich nicht von anderen Handlern in Martini. Du kannst einen Middleware-Handler dem Stack folgendermaßen anfügen:

m.Use(func() {
  // durchlaufe die Middleware
})

Volle Kontrolle über den Middleware Stack erlangst Du mit der Handlers-Funktion. Sie ersetzt jeden zuvor definierten Handler:

m.Handlers(
  Middleware1,
  Middleware2,
  Middleware3,
)

Middleware Handler arbeiten gut mit Aspekten wie Logging, Berechtigungen, Authentifizierung, Sessions, Komprimierung durch gzip, Fehlerseiten und anderen Operationen zusammen, die vor oder nach einer Anfrage passieren.

// überprüfe einen API-Schlüssel
m.Use(func(res http.ResponseWriter, req *http.Request) {
  if req.Header.Get("X-API-KEY") != "secret123" {
    res.WriteHeader(http.StatusUnauthorized)
  }
})

Next()

Context.Next() ist eine optionale Funktion, die Middleware-Handler aufrufen können, um sie nach dem Beenden der anderen Handler auszuführen. Dies funktioniert besonders gut, wenn Operationen nach einer HTTP-Anfrage ausgeführt werden müssen.

// protokolliere vor und nach einer Anfrage
m.Use(func(c martini.Context, log *log.Logger){
  log.Println("vor einer Anfrage")

  c.Next()

  log.Println("nach einer Anfrage")
})

Martini Env

Einige Martini-Handler machen von der globalen martini.Env Variable gebrauch, die der Entwicklungsumgebung erweiterte Funktionen bietet, welche die Produktivumgebung nicht enthält. Es wird empfohlen, die MARTINI_ENV=production Umgebungsvariable zu setzen, sobald der Martini-Server in den Live-Betrieb übergeht.

FAQ

Wo finde ich eine bestimmte Middleware?

Starte die Suche mit einem Blick in die Projekte von martini-contrib. Solltest Du nicht fündig werden, kontaktiere ein Mitglied des martini-contrib Teams, um eine neue Repository anzulegen.

  • acceptlang - Handler zum Parsen des Accept-Language HTTP-Header.
  • accessflags - Handler zur Ermöglichung von Zugriffskontrollen.
  • auth - Handler zur Authentifizierung.
  • binding - Handler zum Zuordnen/Validieren einer Anfrage zu einem Struct.
  • cors - Handler für CORS-Support.
  • csrf - CSRF-Schutz für Applikationen
  • encoder - Enkodierungsservice zum Datenrendering in den verschiedensten Formaten.
  • gzip - Handler zum Ermöglichen von gzip-Kompression bei HTTP-Anfragen.
  • gorelic - NewRelic Middleware
  • logstasher - Middlewaredie Logstashkompatibles JSON ausgibt
  • method - Überschreibe eine HTTP-Method via Header oder Formularfelder.
  • oauth2 - Handler der den Login mit OAuth 2.0 in Martinianwendungen ermöglicht. Google Sign-in, Facebook Connect und Github werden ebenfalls unterstützt.
  • permissions2 - Handler zum Mitverfolgen von Benutzern, Loginstatus und Berechtigungen.
  • render - Handler, der einen einfachen Service zum Rendern von JSON und HTML-Templates bereitstellt.
  • secure - Implementation von Sicherheitsfunktionen
  • sessions - Handler mit einem Session service.
  • sessionauth - Handler zur einfachen Aufforderung eines Logins für Routes und zur Bearbeitung von Benutzerlogins in der Sitzung
  • strict - Strikter Modus.
  • strip - URL-Prefix Stripping.
  • staticbin - Handler for serving static files from binary data
  • throttle - Middleware zum Drosseln von HTTP-Anfragen.
  • vauth - Handler zur Webhook-Authentifizierung (momentan nur GitHub und TravisCI)
  • web - hoisie web.go's Kontext

Wie integriere ich in bestehende Systeme?

Eine Martiniinstanz implementiert http.Handler, sodass Subrouten in bestehenden Servern einfach genutzt werden können. Hier ist eine funktionierende Martinianwendungen für die Google App Engine:

package hello

import (
  "net/http"
  "github.com/go-martini/martini"
)

func init() {
  m := martini.Classic()
  m.Get("/", func() string {
    return "Hallo Welt!"
  })
  http.Handle("/", m)
}

Wie ändere ich den Port/Host?

Martinis Run Funktion sucht automatisch nach den PORT und HOST Umgebungsvariablen, um diese zu nutzen. Andernfalls ist localhost:3000 voreingestellt. Für mehr Flexibilität über den Port und den Host nutze stattdessen die martini.RunOnAddr Funktion.

  m := martini.Classic()
  // ...
  log.Fatal(m.RunOnAddr(":8080"))

Automatisches Aktualisieren?

Gin und Fresh aktualisieren Martini-Apps live.

Bei Martini mitwirken

Martinis Maxime ist Minimalismus und sauberer Code. Die meisten Beiträge sollten sich in den Repositories der martini-contrib Gruppe wiederfinden. Beinhaltet Dein Beitrag Veränderungen am Kern von Martini, zögere nicht, einen Pull Request zu machen.

Über das Projekt

Inspiriert von Express und Sinatra

Martini wird leidenschaftlich von niemand Geringerem als dem Code Gangsta entwickelt