Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bool parameters in json responses are not properly unmarshalled #319

Closed
nlowe opened this issue Jun 6, 2019 · 3 comments · Fixed by #320 or #344
Closed

Bool parameters in json responses are not properly unmarshalled #319

nlowe opened this issue Jun 6, 2019 · 3 comments · Fixed by #320 or #344
Labels
bug This issue is a bug.

Comments

@nlowe
Copy link
Contributor

nlowe commented Jun 6, 2019

Version of AWS SDK for Go?

v0.9.0

Version of Go (go version)?

go version go1.12.1 windows/amd64

What issue did you see?

When sending a GetMethodRequest to the API Gateway API, bool request parameters are incorrectly deserialized.

Steps to reproduce

Given this sample program:

package main

import (
	"context"
	"flag"
	"fmt"

	"github.com/aws/aws-sdk-go-v2/aws/external"
	"github.com/aws/aws-sdk-go-v2/service/apigateway"
)

func main() {
	restApiID := flag.String("rest-api", "", "The Rest API ID")
	resourceID := flag.String("resource", "", "The Resource ID")
	method := flag.String("method", "ANY", "The HTTP Method")

	flag.Parse()

	cfg, err := external.LoadDefaultAWSConfig()
	if err != nil {
		panic(err)
	}

	apigw := apigateway.New(cfg)

	result, err := apigw.GetMethodRequest(&apigateway.GetMethodInput{
		RestApiId:  restApiID,
		ResourceId: resourceID,
		HttpMethod: method,
	}).Send(context.Background())

	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", result)
}

I get the following output:

{
  ApiKeyRequired: false,
  AuthorizationType: "NONE",
  HttpMethod: "ANY",
  MethodIntegration: {
    CacheKeyParameters: ["method.request.path.proxy"],
    CacheNamespace: "***",
    ConnectionType: INTERNET,
    ContentHandling: ,
    HttpMethod: "ANY",
    IntegrationResponses: {
      200: {
        ContentHandling: ,
        ResponseTemplates: {
          application/json: ""
        },
        StatusCode: "200"
      }
    },
    PassthroughBehavior: "WHEN_NO_MATCH",
    RequestParameters: {
      integration.request.path.proxy: "method.request.path.proxy"
    },
    TimeoutInMillis: 29000,
    Type: HTTP_PROXY,
    Uri: "http://***.us-east-1.elb.amazonaws.com/***/{proxy}"
  },
  RequestParameters: {
    method.request.path.proxy: false
  }
}

Notice how RequestParameters["method.request.path.proxy"] is false.

However, when I use the AWS CLI, you can see that it is set to true:

{
    "httpMethod": "ANY",
    "authorizationType": "NONE",
    "apiKeyRequired": false,
    "requestParameters": {
        "method.request.path.proxy": true
    },
    "methodIntegration": {
        "type": "HTTP_PROXY",
        "httpMethod": "ANY",
        "uri": "http://***.us-east-1.elb.amazonaws.com/***/{proxy}",
        "connectionType": "INTERNET",
        "requestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
        },
        "passthroughBehavior": "WHEN_NO_MATCH",
        "timeoutInMillis": 29000,
        "cacheNamespace": "***",
        "cacheKeyParameters": [
            "method.request.path.proxy"
        ],
        "integrationResponses": {
            "200": {
                "statusCode": "200",
                "responseTemplates": {
                    "application/json": null
                }
            }
        }
    }
}

Notice that RequestParameters["method.request.path.proxy"] is actually true.

@nlowe
Copy link
Contributor Author

nlowe commented Jun 7, 2019

I think this is because jsonutil.unmarshalScalar only tries to unmarshal *bool, not bool:

case bool:
switch value.Interface().(type) {
case *bool:
value.Set(reflect.ValueOf(&d))
default:
return errf()

by patching in a case for bool it behaves as expected:

	case bool:
		switch value.Interface().(type) {
		case *bool:
			value.Set(reflect.ValueOf(&d))
		case bool:
			value.Set(reflect.ValueOf(d))
		default:
			return errf()
		}

The error returned by jsonutil.unmarshalScalar is checked by jsonutil.unmarshalAny, but not by jsonutil.unmarshalMap:

for k, v := range mapData {
kvalue := reflect.ValueOf(k)
vvalue := reflect.New(value.Type().Elem()).Elem()
unmarshalAny(vvalue, v, "")
value.SetMapIndex(kvalue, vvalue)
}

So the default of false is used. I believe this will affect any bool field, not just this specific instance that I initially opened the issue for.

@nlowe nlowe changed the title apigateway.GetMethodRequest incorrectly deserializes bool request parameters Bool parameters in json responses are not properly unmarshalled Jun 7, 2019
@nlowe
Copy link
Contributor Author

nlowe commented Jun 7, 2019

Indeed, it looks like it does:

package main

import (
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go-v2/private/protocol/json/jsonutil"
)

type Foo struct {
	Fizz map[string]bool
}

func main() {
	payload := `{"Fizz": {"Buzz": true}}`

	v := &Foo{}
	jsonutil.UnmarshalJSON(v, strings.NewReader(payload))

	fmt.Printf("%+v\n", v)
}

Produces: &{Fizz:map[Buzz:false]} without the patch and &{Fizz:map[Buzz:true]} with it.

@jasdel
Copy link
Contributor

jasdel commented Jun 7, 2019

Thanks for reporting this detailed issue @nlowe. I'm looking into reproduce this issue, but I think the patch you suggested makes sense. The v2 SDK refactored updated list and maps to be values instead of pointers and this looks like a case that might of been missed.

@jasdel jasdel added the bug This issue is a bug. label Jun 7, 2019
jasdel added a commit to jasdel/aws-sdk-go-v2 that referenced this issue Jun 7, 2019
Fixes the JSON unmarshaling of maps of bools. The unmarshal case was
missing the condition for `bool` value, in addition the `bool` pointer.

Fix aws#319
jasdel pushed a commit that referenced this issue Jun 11, 2019
Fixes the JSON unmarshaling of maps of bools. The unmarshal case was
missing the condition for bool value, in addition the bool pointer.

Fix #319
jasdel added a commit to jasdel/aws-sdk-go-v2 that referenced this issue Jul 24, 2019
Services
===
* Synced the V2 SDK with latest AWS service API definitions.
* Fixes [aws#341](aws#341)
* Fixes [aws#342](aws#342)

SDK Breaking Changes
===
* `aws`: Add default HTTP client instead of http.DefaultClient/Transport ([aws#315](aws#315))
  * Adds a new BuildableHTTPClient type to the SDK's aws package. The type uses the builder pattern with immutable changes. Modifications to the buildable client create copies of the client.  Adds a HTTPClient interface to the aws package that the SDK will use as an abstraction over the specific HTTP client implementation. The SDK will default to the BuildableHTTPClient, but a *http.Client can be also provided for custom configuration.  When the SDK's aws.Config.HTTPClient value is a BuildableHTTPClient the SDK will be able to use API client specific request timeout options.
  * Fixes [aws#279](aws#279)
  * Fixes [aws#269](aws#269)

SDK Enhancements
===
* `service/s3/s3manager`: Update S3 Upload Multipart location ([aws#324](aws#324))
  * Updates the Location returned value of S3 Upload's Multipart UploadOutput type to be consistent with single part upload URL. This update also brings the multipart upload Location inline with the S3 object URLs created by the SDK.
  * Fixes [aws#323](aws#323)
  * V2 Port [aws/aws-sdk-go#2453](aws/aws-sdk-go#2453)

SDK Bugs
===
* `private/model`: Handles empty map vs unset map behavior in send request ([aws#337](aws#337))
  * Updated shape marshal model to handle the empty map vs nil map behavior. Adding a test case to assert behavior when a user sends an empty map vs nil map.
  * Fix [aws#332](aws#332)
* `service/rds`: Fix presign URL for same region ([aws#331](aws#331))
  * Fixes RDS no-autopresign URL for same region issue for aws-sdk-go-v2. Solves the issue by making sure that the presigned URLs are not created, when the source and destination regions are the same. Added and updated the tests accordingly.
  * Fix [aws#271](aws#271)
* `private/protocola/json/jsonutil`: Fix Unmarshal map[string]bool ([aws#320](aws#320))
  * Fixes the JSON unmarshaling of maps of bools. The unmarshal case was missing the condition for bool value, in addition the bool pointer.
  * Fix [aws#319](aws#319)
jasdel added a commit that referenced this issue Jul 25, 2019
Services
===
* Synced the V2 SDK with latest AWS service API definitions.
* Fixes [#341](#341)
* Fixes [#342](#342)

SDK Breaking Changes
===
* `aws`: Add default HTTP client instead of http.DefaultClient/Transport ([#315](#315))
  * Adds a new BuildableHTTPClient type to the SDK's aws package. The type uses the builder pattern with immutable changes. Modifications to the buildable client create copies of the client.  Adds a HTTPClient interface to the aws package that the SDK will use as an abstraction over the specific HTTP client implementation. The SDK will default to the BuildableHTTPClient, but a *http.Client can be also provided for custom configuration.  When the SDK's aws.Config.HTTPClient value is a BuildableHTTPClient the SDK will be able to use API client specific request timeout options.
  * Fixes [#279](#279)
  * Fixes [#269](#269)

SDK Enhancements
===
* `service/s3/s3manager`: Update S3 Upload Multipart location ([#324](#324))
  * Updates the Location returned value of S3 Upload's Multipart UploadOutput type to be consistent with single part upload URL. This update also brings the multipart upload Location inline with the S3 object URLs created by the SDK.
  * Fixes [#323](#323)
  * V2 Port [aws/aws-sdk-go#2453](aws/aws-sdk-go#2453)

SDK Bugs
===
* `private/model`: Handles empty map vs unset map behavior in send request ([#337](#337))
  * Updated shape marshal model to handle the empty map vs nil map behavior. Adding a test case to assert behavior when a user sends an empty map vs nil map.
  * Fix [#332](#332)
* `service/rds`: Fix presign URL for same region ([#331](#331))
  * Fixes RDS no-autopresign URL for same region issue for aws-sdk-go-v2. Solves the issue by making sure that the presigned URLs are not created, when the source and destination regions are the same. Added and updated the tests accordingly.
  * Fix [#271](#271)
* `private/protocola/json/jsonutil`: Fix Unmarshal map[string]bool ([#320](#320))
  * Fixes the JSON unmarshaling of maps of bools. The unmarshal case was missing the condition for bool value, in addition the bool pointer.
  * Fix [#319](#319)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug.
Projects
None yet
2 participants