serve restic: add http2 server on stdin/stdout

This commit is contained in:
Alexander Neumann 2018-03-06 23:22:29 +01:00 committed by Nick Craig-Wood
parent f832433fa5
commit 5114b11d6f
4 changed files with 130 additions and 0 deletions

View File

@ -3,9 +3,11 @@ package restic
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"path"
"regexp"
"strconv"
@ -21,10 +23,17 @@ import (
"github.com/ncw/rclone/fs/operations"
"github.com/ncw/rclone/fs/walk"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/net/http2"
)
var (
stdio bool
)
func init() {
httpflags.AddFlags(Command.Flags())
Command.Flags().BoolVar(&stdio, "stdio", false, "run an HTTP2 server on stdin/stdout")
}
// Command definition for cobra
@ -110,6 +119,24 @@ these **must** end with /. Eg
f := cmd.NewFsSrc(args)
cmd.Run(false, true, command, func() error {
s := newServer(f, &httpflags.Opt)
if stdio {
if terminal.IsTerminal(int(os.Stdout.Fd())) {
return errors.New("Refusing to run HTTP2 server directly on a terminal, please let restic start rclone")
}
conn := &StdioConn{
stdin: os.Stdin,
stdout: os.Stdout,
}
httpSrv := &http2.Server{}
opts := &http2.ServeConnOpts{
Handler: http.HandlerFunc(s.handler),
}
httpSrv.ServeConn(conn, opts)
return nil
}
s.serve()
return nil
})

View File

@ -0,0 +1,54 @@
package restic
import (
"log"
"net"
"os"
)
// Addr implements net.Addr for stdin/stdout.
type Addr struct{}
// Network returns the network type as a string.
func (a Addr) Network() string {
return "stdio"
}
func (a Addr) String() string {
return "stdio"
}
// StdioConn implements a net.Conn via stdin/stdout.
type StdioConn struct {
stdin *os.File
stdout *os.File
}
func (s *StdioConn) Read(p []byte) (int, error) {
return s.stdin.Read(p)
}
func (s *StdioConn) Write(p []byte) (int, error) {
return s.stdout.Write(p)
}
// Close closes both streams.
func (s *StdioConn) Close() error {
log.Printf("Server.Close()\n")
err1 := s.stdin.Close()
err2 := s.stdout.Close()
if err1 != nil {
return err1
}
return err2
}
// LocalAddr returns nil.
func (s *StdioConn) LocalAddr() net.Addr {
return Addr{}
}
// RemoteAddr returns nil.
func (s *StdioConn) RemoteAddr() net.Addr {
return Addr{}
}

View File

@ -0,0 +1,27 @@
//+build go1.10
// Deadline setting for go1.10+
package restic
import "time"
// SetDeadline sets the read/write deadline.
func (s *StdioConn) SetDeadline(t time.Time) error {
err1 := s.stdin.SetReadDeadline(t)
err2 := s.stdout.SetWriteDeadline(t)
if err1 != nil {
return err1
}
return err2
}
// SetReadDeadline sets the read/write deadline.
func (s *StdioConn) SetReadDeadline(t time.Time) error {
return s.stdin.SetReadDeadline(t)
}
// SetWriteDeadline sets the read/write deadline.
func (s *StdioConn) SetWriteDeadline(t time.Time) error {
return s.stdout.SetWriteDeadline(t)
}

View File

@ -0,0 +1,22 @@
//+build !go1.10
// Fallback deadline setting for pre go1.10
package restic
import "time"
// SetDeadline sets the read/write deadline.
func (s *StdioConn) SetDeadline(t time.Time) error {
return nil
}
// SetReadDeadline sets the read/write deadline.
func (s *StdioConn) SetReadDeadline(t time.Time) error {
return nil
}
// SetWriteDeadline sets the read/write deadline.
func (s *StdioConn) SetWriteDeadline(t time.Time) error {
return nil
}