提交 2f9c894b 作者: Jeromy Johnson

Merge pull request #2037 from ipfs/header-version-check

Move api version check to header
......@@ -416,17 +416,13 @@ func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.C
return nil, err
}
if client != nil { // daemon is running
if client != nil { // api file exists
if details.cannotRunOnDaemon {
e := "cannot use API with this command."
// check if daemon locked. legacy error text, for now.
daemonLocked, _ := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot)
if daemonLocked {
e = "ipfs daemon is running. please stop it to run this command"
if daemonLocked, _ := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot); daemonLocked {
return nil, cmds.ClientError("ipfs daemon is running. please stop it to run this command")
}
return nil, cmds.ClientError(e)
return nil, nil
}
return client, nil
......@@ -604,63 +600,7 @@ func getApiClient(repoPath, apiAddrStr string) (cmdsHttp.Client, error) {
return nil, err
}
client, err := apiClientForAddr(addr)
if err != nil {
return nil, err
}
// make sure the api is actually running.
// this is slow, as it might mean an RTT to a remote server.
// TODO: optimize some way
if err := apiVersionMatches(client); err != nil {
return nil, err
}
return client, nil
}
// apiVersionMatches checks whether the api server is running the
// same version of go-ipfs. for now, only the exact same version of
// client + server work. In the future, we should use semver for
// proper API versioning! \o/
func apiVersionMatches(client cmdsHttp.Client) (err error) {
ver, err := doVersionRequest(client)
if err != nil {
return err
}
currv := config.CurrentVersionNumber
if ver.Version != currv {
return fmt.Errorf("%s (%s != %s)", errApiVersionMismatch, ver.Version, currv)
}
return nil
}
func doVersionRequest(client cmdsHttp.Client) (*coreCmds.VersionOutput, error) {
cmd := coreCmds.VersionCmd
optDefs, err := cmd.GetOptions([]string{})
if err != nil {
return nil, err
}
req, err := cmds.NewRequest([]string{"version"}, nil, nil, nil, cmd, optDefs)
if err != nil {
return nil, err
}
res, err := client.Send(req)
if err != nil {
if isConnRefused(err) {
err = repo.ErrApiNotRunning
}
return nil, err
}
ver, ok := res.Output().(*coreCmds.VersionOutput)
if !ok {
return nil, errUnexpectedApiOutput
}
return ver, nil
return apiClientForAddr(addr)
}
func apiClientForAddr(addr ma.Multiaddr) (cmdsHttp.Client, error) {
......
......@@ -100,8 +100,7 @@ func (c *client) Send(req cmds.Request) (cmds.Response, error) {
} else {
httpReq.Header.Set(contentTypeHeader, applicationOctetStream)
}
version := config.CurrentVersionNumber
httpReq.Header.Set(uaHeader, fmt.Sprintf("/go-ipfs/%s/", version))
httpReq.Header.Set(uaHeader, config.ApiVersion)
ec := make(chan error, 1)
rc := make(chan cmds.Response, 1)
......
......@@ -14,6 +14,7 @@ import (
cors "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/rs/cors"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
"github.com/ipfs/go-ipfs/repo/config"
cmds "github.com/ipfs/go-ipfs/commands"
logging "github.com/ipfs/go-ipfs/vendor/QmQg1J6vikuXF9oDvm4wpdeAUvvkVEKW1EYDw9HhTMnP2b/go-log"
......@@ -35,7 +36,10 @@ type Handler struct {
corsHandler http.Handler
}
var ErrNotFound = errors.New("404 page not found")
var (
ErrNotFound = errors.New("404 page not found")
errApiVersionMismatch = errors.New("api version mismatch")
)
const (
StreamErrHeader = "X-Stream-Error"
......@@ -423,3 +427,21 @@ func allowReferer(r *http.Request, cfg *ServerConfig) bool {
return false
}
// apiVersionMatches checks whether the api client is running the
// same version of go-ipfs. for now, only the exact same version of
// client + server work. In the future, we should use semver for
// proper API versioning! \o/
func apiVersionMatches(r *http.Request) error {
clientVersion := r.UserAgent()
// skips check if client is not go-ipfs
if clientVersion == "" || !strings.Contains(clientVersion, "/go-ipfs/") {
return nil
}
daemonVersion := config.ApiVersion
if daemonVersion != clientVersion {
return fmt.Errorf("%s (%s != %s)", errApiVersionMismatch, daemonVersion, clientVersion)
}
return nil
}
......@@ -20,12 +20,20 @@ func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
stringArgs := make([]string, 0)
if err := apiVersionMatches(r); err != nil {
if path[0] != "version" { // compatibility with previous version check
return nil, err
}
}
cmd, err := root.Get(path[:len(path)-1])
if err != nil {
// 404 if there is no command at that path
return nil, ErrNotFound
} else if sub := cmd.Subcommand(path[len(path)-1]); sub == nil {
}
if sub := cmd.Subcommand(path[len(path)-1]); sub == nil {
if len(path) <= 1 {
return nil, ErrNotFound
}
......@@ -34,7 +42,6 @@ func Parse(r *http.Request, root *cmds.Command) (cmds.Request, error) {
// e.g. /objects/Qabc12345 (we are passing "Qabc12345" to the "objects" command)
stringArgs = append(stringArgs, path[len(path)-1])
path = path[:len(path)-1]
} else {
cmd = sub
}
......
......@@ -10,6 +10,8 @@ import (
// CurrentVersionNumber is the current application's version literal
const CurrentVersionNumber = "0.3.11-dev"
const ApiVersion = "/go-ipfs/" + CurrentVersionNumber + "/"
// CurrentCommit is the current git commit, this is set as a ldflag in the Makefile
var CurrentCommit string
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论