blob: 85102746c8860a47aa9088efff0cf8bd6dfc58f7 [file] [log] [blame]
// Copyright 2018 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package backend
import (
bspb ""
bytestreamrpc ""
execrpc ""
execlogrpc ""
filerpc ""
// Auth authenticates the request.
type Auth interface {
// Auth checks HTTP access, and returns new context with enduser info.
Auth(context.Context, *http.Request) (context.Context, error)
// GRPC is grpc backend in the same cluster (local) or other cluter (remote).
type GRPC struct {
ByteStreamClient bspb.ByteStreamClient
Auth Auth
// api key. used for remote backend.
APIKey string
// trace prefix and label. used for local backend.
Namespace string
Cluster string
func (g GRPC) httprpcOpts(timeout time.Duration) []httprpc.HandlerOption {
return []httprpc.HandlerOption{
// Ping returns http handler for ping.
func (g GRPC) Ping() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// TODO: hard fail if g.Auth == nil?
if g.Auth != nil {
ctx, err := g.Auth.Auth(req.Context(), req)
if err != nil {
code := http.StatusUnauthorized
logger := log.FromContext(ctx)
logger.Errorf("server error %s: %d %s: %v", req.URL.Path, code, http.StatusText(code), err)
http.Error(w, http.StatusText(code), code)
req = req.WithContext(ctx)
// Accept-Encoding: deflate only if client didn't say gzip,
// since old goma client only recognizes "Accept-Encoding: deflate".
// TODO: always accept gzip, deflate once new goma client released.
if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Accept-Encoding", "gzip, deflate")
} else {
w.Header().Set("Accept-Encoding", "deflate")
// TODO: health status of backend servers?
fmt.Fprintln(w, "ok")
// Exec returns http handler for exec request.
func (g GRPC) Exec() http.Handler {
return execrpc.Handler(g.ExecServer, g.httprpcOpts(5*time.Minute)...)
// ByteStream returns http handler for bytestream.
func (g GRPC) ByteStream() http.Handler {
if g.ByteStreamClient == nil {
return http.HandlerFunc(http.NotFound)
return bytestreamrpc.Handler(g.ByteStreamClient, g.httprpcOpts(1*time.Minute)...)
// StoreFile returns http handler for store file request.
func (g GRPC) StoreFile() http.Handler {
return filerpc.StoreHandler(g.FileServer, g.httprpcOpts(1*time.Minute)...)
// LookupFile returns http handler for lookup file request.
func (g GRPC) LookupFile() http.Handler {
return filerpc.LookupHandler(g.FileServer, g.httprpcOpts(1*time.Minute)...)
// Execlog returns http handler for execlog request.
func (g GRPC) Execlog() http.Handler {
return execlogrpc.Handler(g.ExeclogServer, g.httprpcOpts(1*time.Minute)...)