Browse Source

Add CaptchaServer.

Dmitry Chestnykh 14 years ago
parent
commit
bd0535eaeb
1 changed files with 49 additions and 4 deletions
  1. 49 4
      captcha.go

+ 49 - 4
captcha.go

@@ -4,8 +4,10 @@ import (
 	"bytes"
 	"crypto/rand"
 	"github.com/dchest/uniuri"
+	"http"
 	"io"
 	"os"
+	"path"
 )
 
 const (
@@ -94,12 +96,55 @@ func Verify(id string, digits []byte) bool {
 	return bytes.Equal(digits, reald)
 }
 
-// Collect deletes expired and used captchas from the internal
-// storage. It is called automatically by New function every CollectNum
-// generated captchas, but still exported to enable freeing memory manually if
-// needed.
+// Collect deletes expired or used captchas from the internal storage. It is
+// called automatically by New function every CollectNum generated captchas,
+// but still exported to enable freeing memory manually if needed.
 //
 // Collection is launched in a new goroutine.
 func Collect() {
 	go globalStore.collect()
 }
+
+type captchaHandler struct {
+	imgWidth  int
+	imgHeight int
+}
+
+// CaptchaServer returns a handler that serves HTTP requests with image or
+// audio representations of captchas. Image dimensions are accepted as
+// arguments. The server decides which captcha to serve based on the last URL
+// path component: file name part must contain a captcha id, file extension —
+// its format (PNG or WAV).
+//
+// For example, for file name "B9QTvDV1RXbVJ3Ac.png" it serves an image captcha
+// with id "B9QTvDV1RXbVJ3Ac", and for "B9QTvDV1RXbVJ3Ac.wav" it serves the
+// same captcha in audio format.
+func Server(w, h int) http.Handler { return &captchaHandler{w, h} }
+
+func (h *captchaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	_, file := path.Split(r.URL.Path)
+	ext := path.Ext(file)
+	id := file[:len(file)-len(ext)]
+	if ext == "" || id == "" {
+		http.NotFound(w, r)
+		return
+	}
+	var err os.Error
+	switch ext {
+	case ".png", ".PNG":
+		w.Header().Set("Content-Type", "image/png")
+		err = WriteImage(w, id, h.imgWidth, h.imgHeight)
+	case ".wav", ".WAV":
+		w.Header().Set("Content-Type", "audio/x-wav")
+		err = WriteAudio(w, id)
+	default:
+		err = ErrNotFound
+	}
+	if err != nil {
+		if err == ErrNotFound {
+			http.NotFound(w, r)
+			return
+		}
+		http.Error(w, "error serving captcha", http.StatusInternalServerError)
+	}
+}