浏览代码

fix common request incorrect url issue

Jackson Tian 7 年之前
父节点
当前提交
f7ab2575a8

+ 29 - 29
README.md

@@ -1,15 +1,16 @@
 # Alibaba Cloud Go Software Development Kit
 # Alibaba Cloud Go Software Development Kit
+
 [![Build Status](https://travis-ci.org/aliyun/alibaba-cloud-sdk-go.svg?branch=master)](https://travis-ci.org/aliyun/alibaba-cloud-sdk-go)
 [![Build Status](https://travis-ci.org/aliyun/alibaba-cloud-sdk-go.svg?branch=master)](https://travis-ci.org/aliyun/alibaba-cloud-sdk-go)
 [![Go Report Card](https://goreportcard.com/badge/github.com/aliyun/alibaba-cloud-sdk-go)](https://goreportcard.com/report/github.com/aliyun/alibaba-cloud-sdk-go)
 [![Go Report Card](https://goreportcard.com/badge/github.com/aliyun/alibaba-cloud-sdk-go)](https://goreportcard.com/report/github.com/aliyun/alibaba-cloud-sdk-go)
 [![codecov](https://codecov.io/gh/aliyun/alibaba-cloud-sdk-go/branch/master/graph/badge.svg)](https://codecov.io/gh/aliyun/alibaba-cloud-sdk-go)
 [![codecov](https://codecov.io/gh/aliyun/alibaba-cloud-sdk-go/branch/master/graph/badge.svg)](https://codecov.io/gh/aliyun/alibaba-cloud-sdk-go)
 
 
-[中文文档](./README_zh.md)
+See [中文文档](./README_zh.md)
 
 
 The Alibaba Cloud Go Software Development Kit (SDK) allows you to access Alibaba Cloud services such as Elastic Compute Service (ECS), Server Load Balancer (SLB), and CloudMonitor. You can access Alibaba Cloud services without the need to handle API related tasks, such as signing and constructing your requests.
 The Alibaba Cloud Go Software Development Kit (SDK) allows you to access Alibaba Cloud services such as Elastic Compute Service (ECS), Server Load Balancer (SLB), and CloudMonitor. You can access Alibaba Cloud services without the need to handle API related tasks, such as signing and constructing your requests.
 
 
 This document introduces how to obtain and call Alibaba Cloud Go SDK.
 This document introduces how to obtain and call Alibaba Cloud Go SDK.
 
 
-If you have any problem while using Go SDK, please join the **DingTalk group: 11771185 (the official SDK customer service group of Alibaba Cloud)** for consultation.
+If you have any problem while using Go SDK, please [submit an issue](https://github.com/aliyun/alibaba-cloud-sdk-go/issues/new).
 
 
 ## Prerequisites
 ## Prerequisites
 
 
@@ -22,52 +23,51 @@ If you have any problem while using Go SDK, please join the **DingTalk group: 11
 - To use Alibaba Cloud Go SDK to access the APIs of a product, you must first activate the product on the [Alibaba Cloud console](https://home.console.aliyun.com/?spm=5176.doc52740.2.4.QKZk8w) if required.
 - To use Alibaba Cloud Go SDK to access the APIs of a product, you must first activate the product on the [Alibaba Cloud console](https://home.console.aliyun.com/?spm=5176.doc52740.2.4.QKZk8w) if required.
 
 
 
 
-## Install Go SDK
+## Installation
 
 
 Run the following commands to install Alibaba Cloud Go SDK:
 Run the following commands to install Alibaba Cloud Go SDK:
 
 
 ```powershell
 ```powershell
 glide get github.com/aliyun/alibaba-cloud-sdk-go
 glide get github.com/aliyun/alibaba-cloud-sdk-go
 ```
 ```
-## Use Go SDK
+## Using
 
 
 The following code example shows the three main steps to use Alibaba Cloud Go SDK:
 The following code example shows the three main steps to use Alibaba Cloud Go SDK:
 
 
 1. Create the client.
 1. Create the client.
-
 2. Create an API request and set parameters.
 2. Create an API request and set parameters.
-
 3. Initiate the request and handle exceptions.
 3. Initiate the request and handle exceptions.
 
 
 ```go
 ```go
 package main
 package main
 
 
 import (
 import (
-    "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
-    "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
-    "fmt"
+	"fmt"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
+	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
 )
 )
 
 
 func main() {
 func main() {
-    // Create an ECS client
-    ecsClient, err := ecs.NewClientWithAccessKey(
-        "<your-region-id>",             // Your Region ID
-        "<your-access-key-id>",         // Your AccessKey ID
-        "<your-access-key-secret>")     // Your AccessKey Secret
-    if err != nil {
-        // Handle exceptions
-        panic(err)
-    }
-    // Create an API request and set parameters
-    request := ecs.CreateDescribeInstancesRequest()
-    // Set the request.PageSize to "10"
-    request.PageSize = requests.NewInteger(10)
-    // Initiate the request and handle exceptions
-    response, err := ecsClient.DescribeInstances(request)
-    if err != nil {
-        // Handle exceptions
-        panic(err)
-    }
-    fmt.Println(response)
+	// Create an ECS client
+	ecsClient, err := ecs.NewClientWithAccessKey(
+		"<your-region-id>",         // Your Region ID
+		"<your-access-key-id>",     // Your AccessKey ID
+		"<your-access-key-secret>") // Your AccessKey Secret
+	if err != nil {
+		// Handle exceptions
+		panic(err)
+	}
+	// Create an API request and set parameters
+	request := ecs.CreateDescribeInstancesRequest()
+	// Set the request.PageSize to "10"
+	request.PageSize = requests.NewInteger(10)
+	// Initiate the request and handle exceptions
+	response, err := ecsClient.DescribeInstances(request)
+	if err != nil {
+		// Handle exceptions
+		panic(err)
+	}
+	fmt.Println(response)
 }
 }
 ```
 ```

+ 0 - 57
main.go

@@ -1,57 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"os"
-
-	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
-)
-
-func main() {
-	input := ecs.CreateDescribeRegionsRequest()
-	client, err := ecs.NewClientWithAccessKey("cn-beijing", os.Getenv("ACCESS_KEY_ID"), os.Getenv("ACCESS_KEY_SECRET"))
-	if err != nil {
-		fmt.Printf("Failed to NewClientWithAccessKey! Error: %s\n", err.Error())
-	}
-	output, err := client.DescribeRegions(input)
-	if err != nil {
-		msg := fmt.Sprintf("Failed to DescribeRegions.!")
-		fmt.Printf("%s\nError: %s\n", msg, err.Error())
-		return
-	}
-
-	fmt.Printf("Regions:%s", output.Regions.Region)
-}
-
-// package main
-
-// import (
-// 	"fmt"
-// 	"os"
-
-// 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
-// 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
-// )
-
-// func main() {
-
-// 	client, err := sdk.NewClientWithAccessKey("cn-hangzhou", os.Getenv("ACCESS_KEY_ID"), os.Getenv("ACCESS_KEY_SECRET"))
-// 	if err != nil {
-// 		panic(err)
-// 	}
-
-// 	request := requests.NewCommonRequest()
-// 	// request.Domain = "ecs.aliyuncs.com"
-// 	request.Version = "2014-05-26"
-// 	request.ApiName = "DescribeInstanceStatus"
-
-// 	request.QueryParams["PageNumber"] = "1"
-// 	request.QueryParams["PageSize"] = "30"
-
-// 	response, err := client.ProcessCommonRequest(request)
-// 	if err != nil {
-// 		panic(err)
-// 	}
-
-// 	fmt.Print(response.GetHttpContentString())
-// }

+ 8 - 0
sdk/client.go

@@ -26,8 +26,15 @@ import (
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
 	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
 )
 )
 
 
+var debug utils.Debug
+
+func init() {
+	debug = utils.Init("sdk")
+}
+
 // Version this value will be replaced while build: -ldflags="-X sdk.version=x.x.x"
 // Version this value will be replaced while build: -ldflags="-X sdk.version=x.x.x"
 var Version = "0.0.1"
 var Version = "0.0.1"
 
 
@@ -288,6 +295,7 @@ func buildHttpRequest(request requests.AcsRequest, singer auth.Signer, regionId
 	}
 	}
 	requestMethod := request.GetMethod()
 	requestMethod := request.GetMethod()
 	requestUrl := request.BuildUrl()
 	requestUrl := request.BuildUrl()
+	debug("request URL: %s", requestUrl)
 	body := request.GetBodyReader()
 	body := request.GetBodyReader()
 	httpRequest, err = http.NewRequest(requestMethod, requestUrl, body)
 	httpRequest, err = http.NewRequest(requestMethod, requestUrl, body)
 	if err != nil {
 	if err != nil {

+ 14 - 1
sdk/errors/signature_does_not_match_wrapper.go

@@ -1,10 +1,20 @@
 package errors
 package errors
 
 
-import "strings"
+import (
+	"strings"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils"
+)
 
 
 const SignatureDostNotMatchErrorCode = "SignatureDoesNotMatch"
 const SignatureDostNotMatchErrorCode = "SignatureDoesNotMatch"
 const MessagePrefix = "Specified signature is not matched with our calculation. server string to sign is:"
 const MessagePrefix = "Specified signature is not matched with our calculation. server string to sign is:"
 
 
+var debug utils.Debug
+
+func init() {
+	debug = utils.Init("sdk")
+}
+
 type SignatureDostNotMatchWrapper struct {
 type SignatureDostNotMatchWrapper struct {
 }
 }
 
 
@@ -14,10 +24,13 @@ func (*SignatureDostNotMatchWrapper) tryWrap(error *ServerError, wrapInfo map[st
 		message := error.message
 		message := error.message
 		if strings.HasPrefix(message, MessagePrefix) {
 		if strings.HasPrefix(message, MessagePrefix) {
 			serverStringToSign := message[len(MessagePrefix):]
 			serverStringToSign := message[len(MessagePrefix):]
+
 			if clientStringToSign == serverStringToSign {
 			if clientStringToSign == serverStringToSign {
 				// user secret is error
 				// user secret is error
 				error.recommend = "Please check you AccessKeySecret"
 				error.recommend = "Please check you AccessKeySecret"
 			} else {
 			} else {
+				debug("Client StringToSign: %s", clientStringToSign)
+				debug("Server StringToSign: %s", serverStringToSign)
 				error.recommend = "This may be a bug with the SDK and we hope you can submit this question in the " +
 				error.recommend = "This may be a bug with the SDK and we hope you can submit this question in the " +
 					"github issue(https://github.com/aliyun/alibaba-cloud-sdk-go/issues), thanks very much"
 					"github issue(https://github.com/aliyun/alibaba-cloud-sdk-go/issues), thanks very much"
 			}
 			}

+ 1 - 5
sdk/requests/common_request.go

@@ -86,11 +86,7 @@ func (request *CommonRequest) TransToAcsRequest() {
 }
 }
 
 
 func (request *CommonRequest) BuildUrl() string {
 func (request *CommonRequest) BuildUrl() string {
-	if len(request.Port) > 0 {
-		return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.BuildQueries()
-	}
-
-	return strings.ToLower(request.Scheme) + "://" + request.Domain + request.BuildQueries()
+	return request.Ontology.BuildUrl()
 }
 }
 
 
 func (request *CommonRequest) BuildQueries() string {
 func (request *CommonRequest) BuildQueries() string {

+ 30 - 17
sdk/requests/roa_request.go

@@ -16,6 +16,7 @@ package requests
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"fmt"
 	"io"
 	"io"
 	"net/url"
 	"net/url"
 	"sort"
 	"sort"
@@ -47,23 +48,21 @@ func (request *RoaRequest) GetBodyReader() io.Reader {
 
 
 // for sign method, need not url encoded
 // for sign method, need not url encoded
 func (request *RoaRequest) BuildQueries() string {
 func (request *RoaRequest) BuildQueries() string {
-	return request.buildQueries(false)
+	return request.buildQueries()
 }
 }
 
 
-func (request *RoaRequest) buildQueries(needParamEncode bool) string {
-	// replace path params with value
+func (request *RoaRequest) buildPath() string {
 	path := request.pathPattern
 	path := request.pathPattern
 	for key, value := range request.PathParams {
 	for key, value := range request.PathParams {
 		path = strings.Replace(path, "["+key+"]", value, 1)
 		path = strings.Replace(path, "["+key+"]", value, 1)
 	}
 	}
+	return path
+}
 
 
+func (request *RoaRequest) buildQueries() string {
+	// replace path params with value
+	path := request.buildPath()
 	queryParams := request.QueryParams
 	queryParams := request.QueryParams
-	// check if path contains params
-	// splitArray := strings.Split(path, "?")
-	// path = splitArray[0]
-	// if len(splitArray) > 1 && len(splitArray[1]) > 0 {
-	// 	queryParams[splitArray[1]] = ""
-	// }
 	// sort QueryParams by key
 	// sort QueryParams by key
 	var queryKeys []string
 	var queryKeys []string
 	for key := range queryParams {
 	for key := range queryParams {
@@ -82,11 +81,7 @@ func (request *RoaRequest) buildQueries(needParamEncode bool) string {
 		urlBuilder.WriteString(queryKey)
 		urlBuilder.WriteString(queryKey)
 		if value := queryParams[queryKey]; len(value) > 0 {
 		if value := queryParams[queryKey]; len(value) > 0 {
 			urlBuilder.WriteString("=")
 			urlBuilder.WriteString("=")
-			if needParamEncode {
-				urlBuilder.WriteString(url.QueryEscape(value))
-			} else {
-				urlBuilder.WriteString(value)
-			}
+			urlBuilder.WriteString(value)
 		}
 		}
 		if i < len(queryKeys)-1 {
 		if i < len(queryKeys)-1 {
 			urlBuilder.WriteString("&")
 			urlBuilder.WriteString("&")
@@ -94,8 +89,17 @@ func (request *RoaRequest) buildQueries(needParamEncode bool) string {
 	}
 	}
 	result := urlBuilder.String()
 	result := urlBuilder.String()
 	result = popStandardUrlencode(result)
 	result = popStandardUrlencode(result)
-	request.queries = result
-	return request.queries
+	return result
+}
+
+func (request *RoaRequest) buildQueryString() string {
+	queryParams := request.QueryParams
+	// sort QueryParams by key
+	q := url.Values{}
+	for key, value := range queryParams {
+		q.Add(key, value)
+	}
+	return q.Encode()
 }
 }
 
 
 func popStandardUrlencode(stringToSign string) (result string) {
 func popStandardUrlencode(stringToSign string) (result string) {
@@ -107,7 +111,16 @@ func popStandardUrlencode(stringToSign string) (result string) {
 
 
 func (request *RoaRequest) BuildUrl() string {
 func (request *RoaRequest) BuildUrl() string {
 	// for network trans, need url encoded
 	// for network trans, need url encoded
-	return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.buildQueries(true)
+	scheme := strings.ToLower(request.Scheme)
+	domain := request.Domain
+	port := request.Port
+	path := request.buildPath()
+	url := fmt.Sprintf("%s://%s:%s%s", scheme, domain, port, path)
+	querystring := request.buildQueryString()
+	if len(querystring) > 0 {
+		url = fmt.Sprintf("%s?%s", url, querystring)
+	}
+	return url
 }
 }
 
 
 func (request *RoaRequest) addPathParam(key, value string) {
 func (request *RoaRequest) addPathParam(key, value string) {

+ 4 - 0
sdk/requests/roa_request_test.go

@@ -56,6 +56,8 @@ func Test_RoaRequest_BuildUrl(t *testing.T) {
 	assert.Equal(t, "http://domain.com:80/?key=value", r.BuildUrl())
 	assert.Equal(t, "http://domain.com:80/?key=value", r.BuildUrl())
 	r.addQueryParam("key", "https://domain/?q=v")
 	r.addQueryParam("key", "https://domain/?q=v")
 	assert.Equal(t, "http://domain.com:80/?key=https%3A%2F%2Fdomain%2F%3Fq%3Dv", r.BuildUrl())
 	assert.Equal(t, "http://domain.com:80/?key=https%3A%2F%2Fdomain%2F%3Fq%3Dv", r.BuildUrl())
+	r.addQueryParam("url", "https://domain/?q1=v1&q2=v2")
+	assert.Equal(t, "http://domain.com:80/?key=https%3A%2F%2Fdomain%2F%3Fq%3Dv&url=https%3A%2F%2Fdomain%2F%3Fq1%3Dv1%26q2%3Dv2", r.BuildUrl())
 }
 }
 
 
 func Test_RoaRequest_BuildUrl2(t *testing.T) {
 func Test_RoaRequest_BuildUrl2(t *testing.T) {
@@ -75,6 +77,8 @@ func Test_RoaRequest_BuildUrl2(t *testing.T) {
 	r.Port = "80"
 	r.Port = "80"
 	r.addPathParam("user", "name")
 	r.addPathParam("user", "name")
 	assert.Equal(t, "http://domain.com:80/users/name", r.BuildUrl())
 	assert.Equal(t, "http://domain.com:80/users/name", r.BuildUrl())
+	r.addQueryParam("key", "value")
+	assert.Equal(t, "http://domain.com:80/users/name?key=value", r.BuildUrl())
 }
 }
 
 
 func Test_RoaRequest_GetBodyReader_Nil(t *testing.T) {
 func Test_RoaRequest_GetBodyReader_Nil(t *testing.T) {

+ 6 - 1
sdk/requests/rpc_request.go

@@ -15,6 +15,7 @@
 package requests
 package requests
 
 
 import (
 import (
+	"fmt"
 	"io"
 	"io"
 	"strings"
 	"strings"
 
 
@@ -49,7 +50,11 @@ func (request *RpcRequest) BuildQueries() string {
 }
 }
 
 
 func (request *RpcRequest) BuildUrl() string {
 func (request *RpcRequest) BuildUrl() string {
-	return strings.ToLower(request.Scheme) + "://" + request.Domain + ":" + request.Port + request.BuildQueries()
+	url := fmt.Sprintf("%s://%s", strings.ToLower(request.Scheme), request.Domain)
+	if len(request.Port) > 0 {
+		url = fmt.Sprintf("%s:%s", url, request.Port)
+	}
+	return url + request.BuildQueries()
 }
 }
 
 
 func (request *RpcRequest) GetVersion() string {
 func (request *RpcRequest) GetVersion() string {