emg184
emg184

Reputation: 1010

How to get signed put object url with Amazonka

I am trying to get a presigned url to PUT an object to my s3 bucket. I know the bucket configuration is fine as I've used it for this many times with node and have had no issues. I am currently trying to convert my upload endpoint over to a haskell endpoint as a personal project.

I've tried to use amazonka to egt this however i keep get error messages from AWS and i haven't been able to find a good tutorial on how this might be done. The error messages i am getting are the following:

The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.

I receive a url with the following: https://s3.amazonaws.com/(my-bucket-name)

So i change it to this: https://(my-bucket-name).s3.us-east-2.amazonaws.com After fixing the prefix from the above issue I get the folowing:

Error parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'us-east-2'

However I am setting my Secret Key, Access Key, and the bucket.

Here is a reproducible example:

module Lib
    ( main
    ) where

import ClassyPrelude
import           Network.AWS.S3
import           Network.AWS.S3.PutObject
import           Control.Monad.Trans.AWS
import           Network.AWS.Data
import           Control.Lens

bNameE :: BucketName
bNameE = BucketName <my-bucket-name>

oKeyE :: ObjectKey
oKeyE = ObjectKey ("101/12345-12345-12345-12345.jpg")
-- oKeyE = ObjectKey "photo-106399.jpeg"

sKeyE :: Text
sKeyE = <my-bucket-secret>

aKeyE :: Text
aKeyE = <my-bucket-public>

main :: IO ()
main = do
  r <- getPresignedURL Ohio bNameE oKeyE
  print r

getPresignedURL :: Region
                -> BucketName
                -> ObjectKey
                -> IO ByteString
getPresignedURL r b k = do
    lgr <- newLogger Trace stdout
    env <- newEnv $ FromKeys (AccessKey $ encodeUtf8 $ aKeyE) (SecretKey $ encodeUtf8 $ sKeyE)
    ts  <- getCurrentTime
    let p = (putObject b k "") -- & poContentType .~ (Just "Content-Type=image/jpeg")
    print p
    runResourceT . runAWST env $
        presignURL ts 900 p --(poContentType (Lens'  (Just "Content-Type=jpeg")))

Upvotes: 4

Views: 469

Answers (1)

emg184
emg184

Reputation: 1010

The issue was based on not setting the Region inside of the Env variable you can generate signed URL's with the following:

getPresignedURL :: Region
                -> BucketName
                -> ObjectKey
                -> IO ByteString
getPresignedURL r b k = do
    lgr <- newLogger Trace stdout
    env <- newEnv $ FromKeys (AccessKey $ encodeUtf8 $ aKeyE) (SecretKey $ encodeUtf8 $ sKeyE)
    let nEnv = env & envRegion .~ r
    ts  <- getCurrentTime 
    runResourceT . runAWST nEnv $ presignURL ts 900 (putObject b k "Content-Type=image/jpeg")

Im not very familiar with lenses so i am sure there is a more succinct way to do the following:

    env <- newEnv $ FromKeys (AccessKey $ encodeUtf8 $ aKeyE) (SecretKey $ encodeUtf8 $ sKeyE)
    let nEnv = env & envRegion .~ r

Upvotes: 5

Related Questions