74 lines
2.4 KiB
Go
74 lines
2.4 KiB
Go
package http
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"mime"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
const maxUpdateResultBody = 8 << 20
|
|
|
|
type resultHTTPClient interface {
|
|
Do(*http.Request) (*http.Response, error)
|
|
}
|
|
|
|
type updateResultForwarder struct {
|
|
targetURL string
|
|
client resultHTTPClient
|
|
}
|
|
|
|
// NewUpdateResultForwarder relays the original JSON body to CPONE without
|
|
// forwarding the caller's Authorization header or cookies.
|
|
func NewUpdateResultForwarder(targetURL string, client resultHTTPClient) http.Handler {
|
|
if client == nil {
|
|
client = &http.Client{Timeout: 30 * time.Second}
|
|
}
|
|
return updateResultForwarder{
|
|
targetURL: targetURL,
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
func (h updateResultForwarder) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
|
if err != nil || mediaType != "application/json" {
|
|
WriteJSON(w, http.StatusUnsupportedMediaType, Response{Success: false, Message: "Content-Type harus application/json"})
|
|
return
|
|
}
|
|
body, err := io.ReadAll(io.LimitReader(r.Body, maxUpdateResultBody+1))
|
|
if err != nil {
|
|
WriteJSON(w, http.StatusBadRequest, Response{Success: false, Message: "Gagal membaca payload hasil pemeriksaan"})
|
|
return
|
|
}
|
|
if len(body) > maxUpdateResultBody {
|
|
WriteJSON(w, http.StatusRequestEntityTooLarge, Response{Success: false, Message: "Payload hasil pemeriksaan terlalu besar"})
|
|
return
|
|
}
|
|
var payload map[string]json.RawMessage
|
|
if err := json.Unmarshal(body, &payload); err != nil || payload == nil {
|
|
WriteJSON(w, http.StatusBadRequest, Response{Success: false, Message: "Payload harus berupa object JSON"})
|
|
return
|
|
}
|
|
upstreamRequest, err := http.NewRequestWithContext(r.Context(), http.MethodPost, h.targetURL, bytes.NewReader(body))
|
|
if err != nil {
|
|
WriteJSON(w, http.StatusBadGateway, Response{Success: false, Message: "URL tujuan CPONE tidak valid"})
|
|
return
|
|
}
|
|
upstreamRequest.Header.Set("Content-Type", "application/json")
|
|
upstreamRequest.Header.Set("Accept", "application/json")
|
|
upstreamResponse, err := h.client.Do(upstreamRequest)
|
|
if err != nil {
|
|
WriteJSON(w, http.StatusBadGateway, Response{Success: false, Message: "Gagal menghubungi API hasil pemeriksaan CPONE"})
|
|
return
|
|
}
|
|
defer upstreamResponse.Body.Close()
|
|
if contentType := upstreamResponse.Header.Get("Content-Type"); contentType != "" {
|
|
w.Header().Set("Content-Type", contentType)
|
|
}
|
|
w.WriteHeader(upstreamResponse.StatusCode)
|
|
_, _ = io.Copy(w, upstreamResponse.Body)
|
|
}
|