http: call the credentials callback when facing a 401
The test for now just tests that we can handle returning a `GIT_EUSER` if the caller decides to abort.
This commit is contained in:
parent
464c24ab07
commit
e2eda97316
57
http.go
57
http.go
|
@ -24,7 +24,7 @@ import "C"
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -124,7 +124,7 @@ func (self *ManagedTransport) Action(url string, action SmartService) (SmartSubt
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header["User-Agent"] = []string{"git/2.0 (git2go)"}
|
req.Header["User-Agent"] = []string{"git/2.0 (git2go)"}
|
||||||
return newManagedHttpStream(req), nil
|
return newManagedHttpStream(self, req), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ManagedTransport) Close() error {
|
func (self *ManagedTransport) Close() error {
|
||||||
|
@ -148,14 +148,16 @@ func (self *ManagedTransport) ensureClient() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ManagedHttpStream struct {
|
type ManagedHttpStream struct {
|
||||||
|
owner *ManagedTransport
|
||||||
req *http.Request
|
req *http.Request
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
postBuffer bytes.Buffer
|
postBuffer bytes.Buffer
|
||||||
sentRequest bool
|
sentRequest bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newManagedHttpStream(req *http.Request) *ManagedHttpStream {
|
func newManagedHttpStream(owner *ManagedTransport, req *http.Request) *ManagedHttpStream {
|
||||||
return &ManagedHttpStream{
|
return &ManagedHttpStream{
|
||||||
|
owner: owner,
|
||||||
req: req,
|
req: req,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,12 +184,53 @@ func (self *ManagedHttpStream) Free() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ManagedHttpStream) sendRequest() error {
|
func (self *ManagedHttpStream) sendRequest() error {
|
||||||
self.req.Body = ioutil.NopCloser(&self.postBuffer)
|
var resp *http.Response
|
||||||
resp, err := http.DefaultClient.Do(self.req)
|
var err error
|
||||||
|
var userName string
|
||||||
|
var password string
|
||||||
|
for {
|
||||||
|
req := &http.Request{
|
||||||
|
Method: self.req.Method,
|
||||||
|
URL: self.req.URL,
|
||||||
|
Header: self.req.Header,
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetBasicAuth(userName, password)
|
||||||
|
resp, err = http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusOK {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusUnauthorized {
|
||||||
|
resp.Body.Close()
|
||||||
|
var cred *C.git_cred
|
||||||
|
ret := C.git_transport_smart_credentials(&cred, self.owner.owner, nil, C.GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return MakeGitError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cred.credtype != C.GIT_CREDTYPE_USERPASS_PLAINTEXT {
|
||||||
|
C.git_cred_free(cred)
|
||||||
|
return fmt.Errorf("Unexpected credential type %d", cred.credtype)
|
||||||
|
}
|
||||||
|
ptCred := (*C.git_cred_userpass_plaintext)(unsafe.Pointer(cred))
|
||||||
|
userName = C.GoString(ptCred.username)
|
||||||
|
password = C.GoString(ptCred.password)
|
||||||
|
C.git_cred_free(cred)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any other error we treat as a hard error and punt back to the caller
|
||||||
|
resp.Body.Close()
|
||||||
|
return fmt.Errorf("Unhandled HTTP error %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
self.sentRequest = true
|
self.sentRequest = true
|
||||||
self.resp = resp
|
self.resp = resp
|
||||||
return nil
|
return nil
|
||||||
|
@ -198,6 +241,10 @@ func setLibgit2Error(err error) C.int {
|
||||||
defer C.free(unsafe.Pointer(cstr))
|
defer C.free(unsafe.Pointer(cstr))
|
||||||
C.giterr_set_str(C.GITERR_NET, cstr)
|
C.giterr_set_str(C.GITERR_NET, cstr)
|
||||||
|
|
||||||
|
if gitErr, ok := err.(*GitError); ok {
|
||||||
|
return C.int(gitErr.Code)
|
||||||
|
}
|
||||||
|
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue