github.com/cs3org/reva/v2@v2.27.7/pkg/sdk/common/net/httpreq.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package net 20 21 import ( 22 "context" 23 "fmt" 24 "io" 25 "net/http" 26 "time" 27 ) 28 29 // HTTPRequest performs Reva-specific requests through an HTTP endpoint. 30 type HTTPRequest struct { 31 endpoint string 32 data io.Reader 33 34 client *http.Client 35 request *http.Request 36 } 37 38 func (request *HTTPRequest) initRequest(ctx context.Context, endpoint string, method string, accessToken string, transportToken string, data io.Reader) error { 39 request.endpoint = endpoint 40 request.data = data 41 42 // Initialize the HTTP client 43 request.client = &http.Client{ 44 Timeout: time.Duration(24 * int64(time.Hour)), 45 } 46 47 // Initialize the HTTP request 48 httpReq, err := http.NewRequestWithContext(ctx, method, endpoint, data) 49 if err != nil { 50 return fmt.Errorf("unable to create the HTTP request: %v", err) 51 } 52 request.request = httpReq 53 54 // Set mandatory header values 55 request.request.Header.Set(AccessTokenName, accessToken) 56 request.request.Header.Set(TransportTokenName, transportToken) 57 58 return nil 59 } 60 61 func (request *HTTPRequest) do() (*http.Response, error) { 62 httpRes, err := request.client.Do(request.request) 63 if err != nil { 64 return nil, fmt.Errorf("unable to do the HTTP request: %v", err) 65 } 66 if httpRes.StatusCode != http.StatusOK { 67 return nil, fmt.Errorf("performing the HTTP request failed: %v", httpRes.Status) 68 } 69 return httpRes, nil 70 } 71 72 // AddParameters adds the specified parameters to the request. 73 // The parameters are passed in the query URL. 74 func (request *HTTPRequest) AddParameters(params map[string]string) { 75 query := request.request.URL.Query() 76 for k, v := range params { 77 query.Add(k, v) 78 } 79 request.request.URL.RawQuery = query.Encode() 80 } 81 82 // Do performs the request on the HTTP endpoint and returns the body data. 83 // If checkStatus is set to true, the call will only succeed if the server returns a status code of 200. 84 func (request *HTTPRequest) Do(checkStatus bool) ([]byte, error) { 85 httpRes, err := request.do() 86 if err != nil { 87 return nil, fmt.Errorf("unable to perform the HTTP request for '%v': %v", request.endpoint, err) 88 } 89 defer httpRes.Body.Close() 90 91 if checkStatus && httpRes.StatusCode != http.StatusOK { 92 return nil, fmt.Errorf("received invalid response from '%v': %s", request.endpoint, httpRes.Status) 93 } 94 95 data, err := io.ReadAll(httpRes.Body) 96 if err != nil { 97 return nil, fmt.Errorf("reading response data from '%v' failed: %v", request.endpoint, err) 98 } 99 return data, nil 100 } 101 102 // NewHTTPRequest creates a new HTTP request. 103 func NewHTTPRequest(ctx context.Context, endpoint string, method string, accessToken string, transportToken string, data io.Reader) (*HTTPRequest, error) { 104 request := &HTTPRequest{} 105 if err := request.initRequest(ctx, endpoint, method, accessToken, transportToken, data); err != nil { 106 return nil, fmt.Errorf("unable to initialize the HTTP request: %v", err) 107 } 108 return request, nil 109 }