作者:kristofe
项目:camlistor
func (im *imp) doAPI(ctx *context.Context, result interface{}, apiPath string, keyval ...string) error {
if len(keyval)%2 == 1 {
panic("Incorrect number of keyval arguments. must be even.")
}
if im.creds() == nil {
return fmt.Errorf("No authentication creds")
}
form := url.Values{}
for i := 0; i < len(keyval); i += 2 {
if keyval[i+1] != "" {
form.Set(keyval[i], keyval[i+1])
}
}
fullURL := apiURL + apiPath
res, err := im.doGet(ctx, fullURL, form)
if err != nil {
return err
}
err = httputil.DecodeJSON(res, result)
if err != nil {
return fmt.Errorf("could not parse response for %s: %v", fullURL, err)
}
return nil
}
作者:kdevroed
项目:camlistor
func (im *imp) flickrAPIRequest(result interface{}, method string, keyval ...string) error {
if len(keyval)%2 == 1 {
panic("Incorrect number of keyval arguments")
}
if im.user == nil {
return fmt.Errorf("No authenticated user")
}
form := url.Values{}
form.Set("method", method)
form.Set("format", "json")
form.Set("nojsoncallback", "1")
form.Set("user_id", im.user.Id)
for i := 0; i < len(keyval); i += 2 {
form.Set(keyval[i], keyval[i+1])
}
res, err := im.flickrRequest(apiURL, form)
if err != nil {
return err
}
err = httputil.DecodeJSON(res, result)
if err != nil {
log.Printf("Error parsing response for %s: %s", apiURL, err)
}
return err
}
作者:rfistma
项目:camlistor
// SearchExistingFileSchema does a search query looking for an
// existing file with entire contents of wholeRef, then does a HEAD
// request to verify the file still exists on the server. If so,
// it returns that file schema's blobref.
//
// May return (zero, nil) on ENOENT. A non-nil error is only returned
// if there were problems searching.
func (c *Client) SearchExistingFileSchema(wholeRef blob.Ref) (blob.Ref, error) {
sr, err := c.SearchRoot()
if err != nil {
return blob.Ref{}, err
}
url := sr + "camli/search/files?wholedigest=" + wholeRef.String()
req := c.newRequest("GET", url)
res, err := c.doReqGated(req)
if err != nil {
return blob.Ref{}, err
}
if res.StatusCode != 200 {
body, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
res.Body.Close()
return blob.Ref{}, fmt.Errorf("client: got status code %d from URL %s; body %s", res.StatusCode, url, body)
}
var ress struct {
Files []blob.Ref `json:"files"`
}
if err := httputil.DecodeJSON(res, &ress); err != nil {
return blob.Ref{}, fmt.Errorf("client: error parsing JSON from URL %s: %v", url, err)
}
if len(ress.Files) == 0 {
return blob.Ref{}, nil
}
for _, f := range ress.Files {
if c.FileHasContents(f, wholeRef) {
return f, nil
}
}
return blob.Ref{}, nil
}
作者:hgrecc
项目:camlistor
func (im *imp) doAPI(result interface{}, apiPath string, keyval ...string) error {
if len(keyval)%2 == 1 {
panic("Incorrect number of keyval arguments")
}
token, err := im.tokenCache.Token()
if err != nil {
return fmt.Errorf("Token error: %v", err)
}
form := url.Values{}
form.Set("v", "20140225") // 4sq requires this to version their API
form.Set("oauth_token", token.AccessToken)
for i := 0; i < len(keyval); i += 2 {
form.Set(keyval[i], keyval[i+1])
}
fullURL := apiURL + apiPath
res, err := im.doGet(fullURL, form)
if err != nil {
return err
}
err = httputil.DecodeJSON(res, result)
if err != nil {
log.Printf("Error parsing response for %s: %v", fullURL, err)
}
return err
}
作者:peterwatt
项目:camlistor
func (im *imp) doAPI(result interface{}, apiPath string, keyval ...string) error {
if len(keyval)%2 == 1 {
panic("Incorrect number of keyval arguments")
}
if im.cred == nil {
return fmt.Errorf("No authentication creds")
}
if im.userid == "" {
return fmt.Errorf("No user id")
}
form := url.Values{}
form.Set("user_id", im.userid)
for i := 0; i < len(keyval); i += 2 {
if keyval[i+1] != "" {
form.Set(keyval[i], keyval[i+1])
}
}
res, err := im.doGet(apiURL+apiPath, form)
if err != nil {
return err
}
err = httputil.DecodeJSON(res, result)
if err != nil {
log.Printf("Error parsing response for %s: %s", apiURL, err)
}
return err
}
作者:rfistma
项目:camlistor
// GetJSON sends a GET request to url, and unmarshals the returned
// JSON response into data. The URL's host must match the client's
// configured server.
func (c *Client) GetJSON(url string, data interface{}) error {
if !strings.HasPrefix(url, c.discoRoot()) {
return fmt.Errorf("wrong URL (%q) for this server", url)
}
hreq := c.newRequest("GET", url)
resp, err := c.expect2XX(hreq)
if err != nil {
return err
}
return httputil.DecodeJSON(resp, data)
}
作者:pg
项目:camlistor
// TODO(bradfitz): delete most of this. use new camlistore.org/pkg/blobserver/protocol types instead
// of a map[string]interface{}.
func (c *Client) responseJSONMap(requestName string, resp *http.Response) (map[string]interface{}, error) {
if resp.StatusCode != 200 {
log.Printf("After %s request, failed to JSON from response; status code is %d", requestName, resp.StatusCode)
io.Copy(os.Stderr, resp.Body)
return nil, fmt.Errorf("After %s request, HTTP response code is %d; no JSON to parse.", requestName, resp.StatusCode)
}
jmap := make(map[string]interface{})
if err := httputil.DecodeJSON(resp, &jmap); err != nil {
return nil, err
}
return jmap, nil
}
作者:camarox5
项目:coreos-baremeta
// Remove the list of blobs. An error is returned if the server failed to
// remove a blob. Removing a non-existent blob isn't an error.
func (c *Client) RemoveBlobs(blobs []blob.Ref) error {
if c.sto != nil {
return c.sto.RemoveBlobs(blobs)
}
pfx, err := c.prefix()
if err != nil {
return err
}
url_ := fmt.Sprintf("%s/camli/remove", pfx)
params := make(url.Values) // "blobN" -> BlobRefStr
needsDelete := make(map[string]bool) // BlobRefStr -> true
for n, b := range blobs {
if !b.Valid() {
return errors.New("Cannot delete invalid blobref")
}
key := fmt.Sprintf("blob%v", n+1)
params.Add(key, b.String())
needsDelete[b.String()] = true
}
req, err := http.NewRequest("POST", url_, strings.NewReader(params.Encode()))
if err != nil {
return fmt.Errorf("Error creating RemoveBlobs POST request: %v", err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
c.authMode.AddAuthHeader(req)
resp, err := c.httpClient.Do(req)
if err != nil {
resp.Body.Close()
return fmt.Errorf("Got status code %d from blobserver for remove %s", resp.StatusCode, params.Encode())
}
if resp.StatusCode != 200 {
resp.Body.Close()
return fmt.Errorf("Invalid http response %d in remove response", resp.StatusCode)
}
var remResp removeResponse
if err := httputil.DecodeJSON(resp, &remResp); err != nil {
return fmt.Errorf("Failed to parse remove response: %v", err)
}
for _, value := range remResp.Removed {
delete(needsDelete, value)
}
if len(needsDelete) > 0 {
return fmt.Errorf("Failed to remove blobs %s", strings.Join(stringKeys(needsDelete), ", "))
}
return nil
}
作者:pg
项目:camlistor
func parseStatResponse(res *http.Response) (*statResponse, error) {
var s = &statResponse{HaveMap: make(map[string]blob.SizedRef)}
var pres protocol.StatResponse
if err := httputil.DecodeJSON(res, &pres); err != nil {
return nil, ResponseFormatError(err)
}
s.canLongPoll = pres.CanLongPoll
for _, statItem := range pres.Stat {
br := statItem.Ref
if !br.Valid() {
continue
}
s.HaveMap[br.String()] = blob.SizedRef{br, int64(statItem.Size)}
}
return s, nil
}
作者:rfistma
项目:camlistor
func (c *Client) GetClaims(req *search.ClaimsRequest) (*search.ClaimsResponse, error) {
sr, err := c.SearchRoot()
if err != nil {
return nil, err
}
url := sr + req.URLSuffix()
hreq := c.newRequest("GET", url)
hres, err := c.expect2XX(hreq)
if err != nil {
return nil, err
}
res := new(search.ClaimsResponse)
if err := httputil.DecodeJSON(hres, res); err != nil {
return nil, err
}
return res, nil
}
作者:rfistma
项目:camlistor
// PopulateJSONFromURL makes a GET call at apiURL, using keyval as parameters of
// the associated form. The JSON response is decoded into result.
func (ctx OAuthContext) PopulateJSONFromURL(result interface{}, apiURL string, keyval ...string) error {
if len(keyval)%2 == 1 {
return errors.New("Incorrect number of keyval arguments. must be even.")
}
form := url.Values{}
for i := 0; i < len(keyval); i += 2 {
form.Set(keyval[i], keyval[i+1])
}
hres, err := ctx.Get(apiURL, form)
if err != nil {
return err
}
err = httputil.DecodeJSON(hres, result)
if err != nil {
return fmt.Errorf("could not parse response for %s: %v", apiURL, err)
}
return err
}
作者:pombredann
项目:camlistor
func (im *imp) doAPI(ctx context.Context, form url.Values, result interface{}, apiPath string, keyval ...string) error {
if len(keyval)%2 == 1 {
panic("Incorrect number of keyval arguments")
}
form.Set("v", apiVersion) // 4sq requires this to version their API
for i := 0; i < len(keyval); i += 2 {
form.Set(keyval[i], keyval[i+1])
}
fullURL := apiURL + apiPath
res, err := doGet(ctx, fullURL, form)
if err != nil {
return err
}
err = httputil.DecodeJSON(res, result)
if err != nil {
log.Printf("Error parsing response for %s: %v", fullURL, err)
}
return err
}
作者:rfistma
项目:camlistor
func (c *Client) Query(req *search.SearchQuery) (*search.SearchResult, error) {
sr, err := c.SearchRoot()
if err != nil {
return nil, err
}
url := sr + req.URLSuffix()
body, err := json.MarshalIndent(req, "", "\t")
if err != nil {
return nil, err
}
hreq := c.newRequest("POST", url, bytes.NewReader(body))
hres, err := c.expect2XX(hreq)
if err != nil {
return nil, err
}
res := new(search.SearchResult)
if err := httputil.DecodeJSON(hres, res); err != nil {
return nil, err
}
return res, nil
}
作者:pombredann
项目:camlistor
func (c *Client) Describe(ctx context.Context, req *search.DescribeRequest) (*search.DescribeResponse, error) {
// TODO: use ctx (wait for Go 1.7?)
sr, err := c.SearchRoot()
if err != nil {
return nil, err
}
url := sr + req.URLSuffixPost()
body, err := json.MarshalIndent(req, "", "\t")
if err != nil {
return nil, err
}
hreq := c.newRequest("POST", url, bytes.NewReader(body))
hres, err := c.expect2XX(hreq)
if err != nil {
return nil, err
}
res := new(search.DescribeResponse)
if err := httputil.DecodeJSON(hres, res); err != nil {
return nil, err
}
return res, nil
}
作者:rfistma
项目:camlistor
func (c *Client) doDiscovery() error {
root, err := url.Parse(c.discoRoot())
if err != nil {
return err
}
res, err := c.discoveryResp()
if err != nil {
return err
}
var disco camtypes.Discovery
if err := httputil.DecodeJSON(res, &disco); err != nil {
return err
}
u, err := root.Parse(disco.SearchRoot)
if err != nil {
return fmt.Errorf("client: invalid searchRoot %q; failed to resolve", disco.SearchRoot)
}
c.searchRoot = u.String()
u, err = root.Parse(disco.HelpRoot)
if err != nil {
return fmt.Errorf("client: invalid helpRoot %q; failed to resolve", disco.HelpRoot)
}
c.helpRoot = u.String()
c.storageGen = disco.StorageGeneration
u, err = root.Parse(disco.BlobRoot)
if err != nil {
return fmt.Errorf("client: error resolving blobRoot: %v", err)
}
c.prefixv = strings.TrimRight(u.String(), "/")
if disco.UIDiscovery != nil {
u, err = root.Parse(disco.DownloadHelper)
if err != nil {
return fmt.Errorf("client: invalid downloadHelper %q; failed to resolve", disco.DownloadHelper)
}
c.downloadHelper = u.String()
}
if disco.SyncHandlers != nil {
for _, v := range disco.SyncHandlers {
ufrom, err := root.Parse(v.From)
if err != nil {
return fmt.Errorf("client: invalid %q \"from\" sync; failed to resolve", v.From)
}
uto, err := root.Parse(v.To)
if err != nil {
return fmt.Errorf("client: invalid %q \"to\" sync; failed to resolve", v.To)
}
c.syncHandlers = append(c.syncHandlers, &SyncInfo{
From: ufrom.String(),
To: uto.String(),
ToIndex: v.ToIndex,
})
}
}
if disco.Signing != nil {
c.serverKeyID = disco.Signing.PublicKeyID
}
return nil
}
作者:pg
项目:camlistor
func (c *Client) doDiscovery() error {
root, err := url.Parse(c.discoRoot())
if err != nil {
return err
}
// If the path is just "" or "/", do discovery against
// the URL to see which path we should actually use.
req := c.newRequest("GET", c.discoRoot(), nil)
req.Header.Set("Accept", "text/x-camli-configuration")
res, err := c.doReqGated(req)
if err != nil {
return err
}
if res.StatusCode != 200 {
res.Body.Close()
return fmt.Errorf("Got status %q from blobserver URL %q during configuration discovery", res.Status, c.discoRoot())
}
// TODO(bradfitz): little weird in retrospect that we request
// text/x-camli-configuration and expect to get back
// text/javascript. Make them consistent.
if ct := res.Header.Get("Content-Type"); ct != "text/javascript" {
res.Body.Close()
return fmt.Errorf("Blobserver returned unexpected type %q from discovery", ct)
}
// TODO: make a proper struct type for this in another package somewhere:
m := make(map[string]interface{})
if err := httputil.DecodeJSON(res, &m); err != nil {
return err
}
searchRoot, ok := m["searchRoot"].(string)
if ok {
u, err := root.Parse(searchRoot)
if err != nil {
return fmt.Errorf("client: invalid searchRoot %q; failed to resolve", searchRoot)
}
c.searchRoot = u.String()
}
downloadHelper, ok := m["downloadHelper"].(string)
if ok {
u, err := root.Parse(downloadHelper)
if err != nil {
return fmt.Errorf("client: invalid downloadHelper %q; failed to resolve", downloadHelper)
}
c.downloadHelper = u.String()
}
c.storageGen, _ = m["storageGeneration"].(string)
blobRoot, ok := m["blobRoot"].(string)
if !ok {
return fmt.Errorf("No blobRoot in config discovery response")
}
u, err := root.Parse(blobRoot)
if err != nil {
return fmt.Errorf("client: error resolving blobRoot: %v", err)
}
c.prefixv = strings.TrimRight(u.String(), "/")
syncHandlers, ok := m["syncHandlers"].([]interface{})
if ok {
for _, v := range syncHandlers {
vmap := v.(map[string]interface{})
from := vmap["from"].(string)
ufrom, err := root.Parse(from)
if err != nil {
return fmt.Errorf("client: invalid %q \"from\" sync; failed to resolve", from)
}
to := vmap["to"].(string)
uto, err := root.Parse(to)
if err != nil {
return fmt.Errorf("client: invalid %q \"to\" sync; failed to resolve", to)
}
toIndex, _ := vmap["toIndex"].(bool)
c.syncHandlers = append(c.syncHandlers, &SyncInfo{
From: ufrom.String(),
To: uto.String(),
ToIndex: toIndex,
})
}
}
return nil
}
作者:sfrdm
项目:camlistor
func (c *Client) doDiscovery() error {
root, err := url.Parse(c.discoRoot())
if err != nil {
return err
}
res, err := c.discoveryResp()
if err != nil {
return err
}
// TODO: make a proper struct type for this in another package somewhere:
m := make(map[string]interface{})
if err := httputil.DecodeJSON(res, &m); err != nil {
return err
}
searchRoot, ok := m["searchRoot"].(string)
if ok {
u, err := root.Parse(searchRoot)
if err != nil {
return fmt.Errorf("client: invalid searchRoot %q; failed to resolve", searchRoot)
}
c.searchRoot = u.String()
}
downloadHelper, ok := m["downloadHelper"].(string)
if ok {
u, err := root.Parse(downloadHelper)
if err != nil {
return fmt.Errorf("client: invalid downloadHelper %q; failed to resolve", downloadHelper)
}
c.downloadHelper = u.String()
}
c.storageGen, _ = m["storageGeneration"].(string)
blobRoot, ok := m["blobRoot"].(string)
if !ok {
return fmt.Errorf("No blobRoot in config discovery response")
}
u, err := root.Parse(blobRoot)
if err != nil {
return fmt.Errorf("client: error resolving blobRoot: %v", err)
}
c.prefixv = strings.TrimRight(u.String(), "/")
syncHandlers, ok := m["syncHandlers"].([]interface{})
if ok {
for _, v := range syncHandlers {
vmap := v.(map[string]interface{})
from := vmap["from"].(string)
ufrom, err := root.Parse(from)
if err != nil {
return fmt.Errorf("client: invalid %q \"from\" sync; failed to resolve", from)
}
to := vmap["to"].(string)
uto, err := root.Parse(to)
if err != nil {
return fmt.Errorf("client: invalid %q \"to\" sync; failed to resolve", to)
}
toIndex, _ := vmap["toIndex"].(bool)
c.syncHandlers = append(c.syncHandlers, &SyncInfo{
From: ufrom.String(),
To: uto.String(),
ToIndex: toIndex,
})
}
}
serverSigning, ok := m["signing"].(map[string]interface{})
if ok {
c.serverKeyID = serverSigning["publicKeyId"].(string)
}
return nil
}
作者:camarox5
项目:coreos-baremeta
//.........这里部分代码省略.........
}
if env.DebugUploads() {
log.Printf("Uploading: %s (%d bytes)", blobrefStr, bodySize)
}
pipeReader, pipeWriter := io.Pipe()
multipartWriter := multipart.NewWriter(pipeWriter)
copyResult := make(chan error, 1)
go func() {
defer pipeWriter.Close()
part, err := multipartWriter.CreateFormFile(blobrefStr, blobrefStr)
if err != nil {
copyResult <- err
return
}
_, err = io.Copy(part, bodyReader)
if err == nil {
err = multipartWriter.Close()
}
copyResult <- err
}()
// TODO(bradfitz): verbosity levels. make this VLOG(2) or something. it's noisy:
// c.log.Printf("Uploading %s", br)
uploadURL := fmt.Sprintf("%s/camli/upload", pfx)
req := c.newRequest("POST", uploadURL)
req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
if h.Vivify {
req.Header.Add("X-Camlistore-Vivify", "1")
}
req.Body = ioutil.NopCloser(pipeReader)
req.ContentLength = multipartOverhead + bodySize + int64(len(blobrefStr))*2
resp, err := c.doReqGated(req)
if err != nil {
return errorf("upload http error: %v", err)
}
defer resp.Body.Close()
// check error from earlier copy
if err := <-copyResult; err != nil {
return errorf("failed to copy contents into multipart writer: %v", err)
}
// The only valid HTTP responses are 200 and 303.
if resp.StatusCode != 200 && resp.StatusCode != 303 {
return errorf("invalid http response %d in upload response", resp.StatusCode)
}
if resp.StatusCode == 303 {
otherLocation := resp.Header.Get("Location")
if otherLocation == "" {
return errorf("303 without a Location")
}
baseURL, _ := url.Parse(uploadURL)
absURL, err := baseURL.Parse(otherLocation)
if err != nil {
return errorf("303 Location URL relative resolve error: %v", err)
}
otherLocation = absURL.String()
resp, err = http.Get(otherLocation)
if err != nil {
return errorf("error following 303 redirect after upload: %v", err)
}
}
var ures protocol.UploadResponse
if err := httputil.DecodeJSON(resp, &ures); err != nil {
return errorf("error in upload response: %v", err)
}
if ures.ErrorText != "" {
c.log.Printf("Blob server reports error: %s", ures.ErrorText)
}
expectedSize := uint32(bodySize)
for _, sb := range ures.Received {
if sb.Ref != h.BlobRef {
continue
}
if sb.Size != expectedSize {
return errorf("Server got blob %v, but reports wrong length (%v; we sent %d)",
sb.Ref, sb.Size, expectedSize)
}
c.statsMutex.Lock()
c.stats.Uploads.Blobs++
c.stats.Uploads.Bytes += bodySize
c.statsMutex.Unlock()
if pr.Size <= 0 {
pr.Size = sb.Size
}
c.haveCache.NoteBlobExists(pr.BlobRef, pr.Size)
return pr, nil
}
return nil, errors.New("Server didn't receive blob.")
}