Skip to content

Commit

Permalink
Chore: Add swagger examples & API code restructure
Browse files Browse the repository at this point in the history
  • Loading branch information
axllent committed Nov 9, 2024
1 parent 8f79fcd commit 657cada
Show file tree
Hide file tree
Showing 16 changed files with 1,479 additions and 1,344 deletions.
676 changes: 0 additions & 676 deletions server/apiv1/api.go

Large diffs are not rendered by default.

49 changes: 46 additions & 3 deletions server/apiv1/webui.go → server/apiv1/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,41 @@ import (
"net/http"

"github.com/axllent/mailpit/config"
"github.com/axllent/mailpit/internal/stats"
)

// Application information
// swagger:response AppInfoResponse
type appInfoResponse struct {
// Application information
//
// in: body
Body stats.AppInformation
}

// AppInfo returns some basic details about the running app, and latest release.
func AppInfo(w http.ResponseWriter, _ *http.Request) {
// swagger:route GET /api/v1/info application AppInformation
//
// # Get application information
//
// Returns basic runtime information, message totals and latest release version.
//
// Produces:
// - application/json
//
// Schemes: http, https
//
// Responses:
// 200: AppInfoResponse
// 400: ErrorResponse

w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(stats.Load()); err != nil {
httpError(w, err.Error())
}
}

// Response includes global web UI settings
//
// swagger:model WebUIConfiguration
Expand Down Expand Up @@ -38,6 +71,15 @@ type webUIConfiguration struct {
DuplicatesIgnored bool
}

// Web UI configuration response
// swagger:response WebUIConfigurationResponse
type webUIConfigurationResponse struct {
// Web UI configuration settings
//
// in: body
Body webUIConfiguration
}

// WebUIConfig returns configuration settings for the web UI.
func WebUIConfig(w http.ResponseWriter, _ *http.Request) {
// swagger:route GET /api/v1/webui application WebUIConfiguration
Expand All @@ -48,13 +90,14 @@ func WebUIConfig(w http.ResponseWriter, _ *http.Request) {
// Intended for web UI only!
//
// Produces:
// - application/json
// - application/json
//
// Schemes: http, https
//
// Responses:
// 200: WebUIConfigurationResponse
// default: ErrorResponse
// 200: WebUIConfigurationResponse
// 400: ErrorResponse

conf := webUIConfiguration{}

conf.Label = config.Label
Expand Down
31 changes: 0 additions & 31 deletions server/apiv1/info.go

This file was deleted.

252 changes: 252 additions & 0 deletions server/apiv1/message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
package apiv1

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/mail"

"github.com/axllent/mailpit/internal/storage"
"github.com/gorilla/mux"
)

// swagger:parameters GetMessageParams
type getMessageParams struct {
// Message database ID or "latest"
//
// in: path
// required: true
// example: 4oRBnPtCXgAqZniRhzLNmS
ID string
}

// GetMessage (method: GET) returns the Message as JSON
func GetMessage(w http.ResponseWriter, r *http.Request) {
// swagger:route GET /api/v1/message/{ID} message GetMessageParams
//
// # Get message summary
//
// Returns the summary of a message, marking the message as read.
//
// The ID can be set to `latest` to return the latest message.
//
// Produces:
// - application/json
//
// Schemes: http, https
//
// Responses:
// 200: Message
// 400: ErrorResponse
// 404: NotFoundResponse

vars := mux.Vars(r)

id := vars["id"]

if id == "latest" {
var err error
id, err = storage.LatestID(r)
if err != nil {
w.WriteHeader(404)
fmt.Fprint(w, err.Error())
return
}
}

msg, err := storage.GetMessage(id)
if err != nil {
fourOFour(w)
return
}

w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(msg); err != nil {
httpError(w, err.Error())
}
}

// swagger:parameters GetHeadersParams
type getHeadersParams struct {
// Message database ID or "latest"
//
// in: path
// required: true
// example: 4oRBnPtCXgAqZniRhzLNmS
ID string
}

// Message headers
// swagger:model MessageHeadersResponse
type messageHeaders map[string][]string

// GetHeaders (method: GET) returns the message headers as JSON
func GetHeaders(w http.ResponseWriter, r *http.Request) {
// swagger:route GET /api/v1/message/{ID}/headers message GetHeadersParams
//
// # Get message headers
//
// Returns the message headers as an array. Note that header keys are returned alphabetically.
//
// The ID can be set to `latest` to return the latest message headers.
//
// Produces:
// - application/json
//
// Schemes: http, https
//
// Responses:
// 200: MessageHeadersResponse
// 400: ErrorResponse
// 404: NotFoundResponse

vars := mux.Vars(r)

id := vars["id"]

if id == "latest" {
var err error
id, err = storage.LatestID(r)
if err != nil {
w.WriteHeader(404)
fmt.Fprint(w, err.Error())
return
}
}

data, err := storage.GetMessageRaw(id)
if err != nil {
fourOFour(w)
return
}

reader := bytes.NewReader(data)
m, err := mail.ReadMessage(reader)
if err != nil {
httpError(w, err.Error())
return
}

w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(m.Header); err != nil {
httpError(w, err.Error())
}
}

// swagger:parameters AttachmentParams
type attachmentParams struct {
// Message database ID or "latest"
//
// in: path
// required: true
// example: 4oRBnPtCXgAqZniRhzLNmS
ID string

// Attachment part ID
//
// in: path
// required: true
// example: 2
PartID string
}

// DownloadAttachment (method: GET) returns the attachment data
func DownloadAttachment(w http.ResponseWriter, r *http.Request) {
// swagger:route GET /api/v1/message/{ID}/part/{PartID} message AttachmentParams
//
// # Get message attachment
//
// This will return the attachment part using the appropriate Content-Type.
//
// The ID can be set to `latest` to reference the latest message.
//
// Produces:
// - application/*
// - image/*
// - text/*
//
// Schemes: http, https
//
// Responses:
// 200: BinaryResponse
// 400: ErrorResponse
// 404: NotFoundResponse

vars := mux.Vars(r)

id := vars["id"]
partID := vars["partID"]

a, err := storage.GetAttachmentPart(id, partID)
if err != nil {
fourOFour(w)
return
}
fileName := a.FileName
if fileName == "" {
fileName = a.ContentID
}

w.Header().Add("Content-Type", a.ContentType)
w.Header().Set("Content-Disposition", "filename=\""+fileName+"\"")
_, _ = w.Write(a.Content)
}

// swagger:parameters DownloadRawParams
type downloadRawParams struct {
// Message database ID or "latest"
//
// in: path
// required: true
// example: 4oRBnPtCXgAqZniRhzLNmS
ID string
}

// DownloadRaw (method: GET) returns the full email source as plain text
func DownloadRaw(w http.ResponseWriter, r *http.Request) {
// swagger:route GET /api/v1/message/{ID}/raw message DownloadRawParams
//
// # Get message source
//
// Returns the full email source as plain text.
//
// The ID can be set to `latest` to return the latest message source.
//
// Produces:
// - text/plain
//
// Schemes: http, https
//
// Responses:
// 200: TextResponse
// 400: ErrorResponse
// 404: NotFoundResponse

vars := mux.Vars(r)

id := vars["id"]
dl := r.FormValue("dl")

if id == "latest" {
var err error
id, err = storage.LatestID(r)
if err != nil {
w.WriteHeader(404)
fmt.Fprint(w, err.Error())
return
}
}

data, err := storage.GetMessageRaw(id)
if err != nil {
fourOFour(w)
return
}

w.Header().Set("Content-Type", "text/plain; charset=utf-8")
if dl == "1" {
w.Header().Set("Content-Disposition", "attachment; filename=\""+id+".eml\"")
}
_, _ = w.Write(data)
}
Loading

0 comments on commit 657cada

Please sign in to comment.