194 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
| package storage
 | |
| 
 | |
| // Copyright (c) Microsoft Corporation. All rights reserved.
 | |
| // Licensed under the MIT License. See License.txt in the project root for license information.
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"net/http"
 | |
| 	"net/url"
 | |
| 	"strconv"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	headerAccept          = "Accept"
 | |
| 	headerEtag            = "Etag"
 | |
| 	headerPrefer          = "Prefer"
 | |
| 	headerXmsContinuation = "x-ms-Continuation-NextTableName"
 | |
| )
 | |
| 
 | |
| // TableServiceClient contains operations for Microsoft Azure Table Storage
 | |
| // Service.
 | |
| type TableServiceClient struct {
 | |
| 	client Client
 | |
| 	auth   authentication
 | |
| }
 | |
| 
 | |
| // TableOptions includes options for some table operations
 | |
| type TableOptions struct {
 | |
| 	RequestID string
 | |
| }
 | |
| 
 | |
| func (options *TableOptions) addToHeaders(h map[string]string) map[string]string {
 | |
| 	if options != nil {
 | |
| 		h = addToHeaders(h, "x-ms-client-request-id", options.RequestID)
 | |
| 	}
 | |
| 	return h
 | |
| }
 | |
| 
 | |
| // QueryNextLink includes information for getting the next page of
 | |
| // results in query operations
 | |
| type QueryNextLink struct {
 | |
| 	NextLink *string
 | |
| 	ml       MetadataLevel
 | |
| }
 | |
| 
 | |
| // GetServiceProperties gets the properties of your storage account's table service.
 | |
| // See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/get-table-service-properties
 | |
| func (t *TableServiceClient) GetServiceProperties() (*ServiceProperties, error) {
 | |
| 	return t.client.getServiceProperties(tableServiceName, t.auth)
 | |
| }
 | |
| 
 | |
| // SetServiceProperties sets the properties of your storage account's table service.
 | |
| // See: https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/set-table-service-properties
 | |
| func (t *TableServiceClient) SetServiceProperties(props ServiceProperties) error {
 | |
| 	return t.client.setServiceProperties(props, tableServiceName, t.auth)
 | |
| }
 | |
| 
 | |
| // GetTableReference returns a Table object for the specified table name.
 | |
| func (t *TableServiceClient) GetTableReference(name string) *Table {
 | |
| 	return &Table{
 | |
| 		tsc:  t,
 | |
| 		Name: name,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // QueryTablesOptions includes options for some table operations
 | |
| type QueryTablesOptions struct {
 | |
| 	Top       uint
 | |
| 	Filter    string
 | |
| 	RequestID string
 | |
| }
 | |
| 
 | |
| func (options *QueryTablesOptions) getParameters() (url.Values, map[string]string) {
 | |
| 	query := url.Values{}
 | |
| 	headers := map[string]string{}
 | |
| 	if options != nil {
 | |
| 		if options.Top > 0 {
 | |
| 			query.Add(OdataTop, strconv.FormatUint(uint64(options.Top), 10))
 | |
| 		}
 | |
| 		if options.Filter != "" {
 | |
| 			query.Add(OdataFilter, options.Filter)
 | |
| 		}
 | |
| 		headers = addToHeaders(headers, "x-ms-client-request-id", options.RequestID)
 | |
| 	}
 | |
| 	return query, headers
 | |
| }
 | |
| 
 | |
| // QueryTables returns the tables in the storage account.
 | |
| // You can use query options defined by the OData Protocol specification.
 | |
| //
 | |
| // See https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/query-tables
 | |
| func (t *TableServiceClient) QueryTables(ml MetadataLevel, options *QueryTablesOptions) (*TableQueryResult, error) {
 | |
| 	query, headers := options.getParameters()
 | |
| 	uri := t.client.getEndpoint(tableServiceName, tablesURIPath, query)
 | |
| 	return t.queryTables(uri, headers, ml)
 | |
| }
 | |
| 
 | |
| // NextResults returns the next page of results
 | |
| // from a QueryTables or a NextResults operation.
 | |
| //
 | |
| // See https://docs.microsoft.com/rest/api/storageservices/fileservices/query-tables
 | |
| // See https://docs.microsoft.com/rest/api/storageservices/fileservices/query-timeout-and-pagination
 | |
| func (tqr *TableQueryResult) NextResults(options *TableOptions) (*TableQueryResult, error) {
 | |
| 	if tqr == nil {
 | |
| 		return nil, errNilPreviousResult
 | |
| 	}
 | |
| 	if tqr.NextLink == nil {
 | |
| 		return nil, errNilNextLink
 | |
| 	}
 | |
| 	headers := options.addToHeaders(map[string]string{})
 | |
| 
 | |
| 	return tqr.tsc.queryTables(*tqr.NextLink, headers, tqr.ml)
 | |
| }
 | |
| 
 | |
| // TableQueryResult contains the response from
 | |
| // QueryTables and QueryTablesNextResults functions.
 | |
| type TableQueryResult struct {
 | |
| 	OdataMetadata string  `json:"odata.metadata"`
 | |
| 	Tables        []Table `json:"value"`
 | |
| 	QueryNextLink
 | |
| 	tsc *TableServiceClient
 | |
| }
 | |
| 
 | |
| func (t *TableServiceClient) queryTables(uri string, headers map[string]string, ml MetadataLevel) (*TableQueryResult, error) {
 | |
| 	if ml == EmptyPayload {
 | |
| 		return nil, errEmptyPayload
 | |
| 	}
 | |
| 	headers = mergeHeaders(headers, t.client.getStandardHeaders())
 | |
| 	headers[headerAccept] = string(ml)
 | |
| 
 | |
| 	resp, err := t.client.exec(http.MethodGet, uri, headers, nil, t.auth)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer resp.Body.Close()
 | |
| 
 | |
| 	if err := checkRespCode(resp, []int{http.StatusOK}); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	respBody, err := ioutil.ReadAll(resp.Body)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	var out TableQueryResult
 | |
| 	err = json.Unmarshal(respBody, &out)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	for i := range out.Tables {
 | |
| 		out.Tables[i].tsc = t
 | |
| 	}
 | |
| 	out.tsc = t
 | |
| 
 | |
| 	nextLink := resp.Header.Get(http.CanonicalHeaderKey(headerXmsContinuation))
 | |
| 	if nextLink == "" {
 | |
| 		out.NextLink = nil
 | |
| 	} else {
 | |
| 		originalURI, err := url.Parse(uri)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		v := originalURI.Query()
 | |
| 		v.Set(nextTableQueryParameter, nextLink)
 | |
| 		newURI := t.client.getEndpoint(tableServiceName, tablesURIPath, v)
 | |
| 		out.NextLink = &newURI
 | |
| 		out.ml = ml
 | |
| 	}
 | |
| 
 | |
| 	return &out, nil
 | |
| }
 | |
| 
 | |
| func addBodyRelatedHeaders(h map[string]string, length int) map[string]string {
 | |
| 	h[headerContentType] = "application/json"
 | |
| 	h[headerContentLength] = fmt.Sprintf("%v", length)
 | |
| 	h[headerAcceptCharset] = "UTF-8"
 | |
| 	return h
 | |
| }
 | |
| 
 | |
| func addReturnContentHeaders(h map[string]string, ml MetadataLevel) map[string]string {
 | |
| 	if ml != EmptyPayload {
 | |
| 		h[headerPrefer] = "return-content"
 | |
| 		h[headerAccept] = string(ml)
 | |
| 	} else {
 | |
| 		h[headerPrefer] = "return-no-content"
 | |
| 		// From API version 2015-12-11 onwards, Accept header is required
 | |
| 		h[headerAccept] = string(NoMetadata)
 | |
| 	}
 | |
| 	return h
 | |
| }
 |