This post is about the correct way to use os.Stdin for S3 uploading using AWSK Go SDK.

Recently I was writing a CLI app that is supposed to read data from stdin and upload it into S3 using AWS Go SDK. The implementation was straightforward but the app terminated with the error seek /dev/stdin: illegal seek.

The usage of stdin with S3 SDK is something similiar to below snippet

    uploadInput := &s3.PutObjectInput{
        Bucket: bucket,
        Key:    key,
        Body:   os.Stdin,
    }

Further investigation revealed that AWS Go SDK internally checks the type of Body and it tries to determine the length of the body by seeking if the type supports the Seek method.

Incidentally, os.Stdin is of type os.File which provides Seek method(eventhough it fails with an error). So AWS SDK tries to determine the length of Body which triggers the error I mentioned above.

One way we can avoid the length determination(and the error) is by hiding the fact that os.Stdin the Seek method. We can do this by simply wrapping os.Stdin with io.MultiReader which provides Read method only.

So I got the app working by changing the stdin usage like below

    uploadInput := &s3.PutObjectInput{
        Bucket: bucket,
        Key:    key,
        Body:   io.MultiReader(os.Stdin),
    }

Checkout this link for Robpike proposal to change io.StdXXX in Go 2. Thanks to https://twitter.com/sudproquo for the link.