2016-04-04 8 views
3

Ich verwende AWS Lambda, um einen einfachen Upload-Service für mein mobiles Produkt zu erstellen.AWS signierte URLs funktionieren überall außer Android

Auf dem Server erstelle ich einen presigned URL den folgenden Code

var params = { 
    Bucket: targetS3Bucket, 
    Key: key, 
    Body: '', 
    ContentType: event.contentType, 
    Expires: 60 
}; 

s3.getSignedUrl('putObject', params, function (err, url){ 
    context.done(null, { 
     'oneTimeUploadUrl': url, 
     'resultUrl': urlPrefix + key 
    }); 
}); 

mit Wo targetS3Bucket ein Pfad zu einem Ordner auf S3 ist, key der Name der Datei selbst und urlPrefix ist die Wurzel der HTTP-Speicherort der Datei auf S3 (dh: s3.amazonaws.com/some-folder/)

mit Hilfe dieses Codes mit einer integrierten HTTP-Bibliothek (das heißt, nicht jede aws SDK) arbeitet ohne Fehler auf dem PC und iOS, aber nicht auf Android.

Die neueste Version des Android-Client-Code wie folgt aussieht:

uri = new URL(oneTimeUploadUrl); 

// Setup Connection 
HttpsURLConnection http = (HttpsURLConnection) uri.openConnection(); 
http.setDoOutput(true); 
http.setRequestMethod("PUT"); 
​ 
// Write Data 
OutputStream os = http.getOutputStream(); 
os.write(_bytes); 
os.flush(); 
os.close(); // request gets sent off to the server 

Dies schlägt fehl konsequent mit Code 400. Ich habe verschiedene Dinge ausprobiert, wie das Ändern der Codierung, die Verwendung der Nicht-https-Version von HttpsURLConnection und ein paar andere Dinge, aber ohne Erfolg.

Ich würde es vorziehen, das AWS SDK zu vermeiden, da ich nur diese einzige Funktion benötigt, und die Verwendung dieser lambada-seitigen Lösung hat dies auf allen Plattformen außer Android möglich gemacht.

Hier ist die von AWS zurückgegebene XML. Die Nachricht, die zurückgegeben wird, ist verwirrend, da der Client das Token nie ändert und derselbe Prozess auf anderen Geräten erfolgreich ist.

<?xml version="1.0" encoding="UTF-8"?> 
<Error> 
    <Code>InvalidToken</Code> 
    <Message>The provided token is malformed or otherwise invalid.</Message> 
    <Token-0>{Token-0}</Token-0> 
    <RequestId>{RequestId}</RequestId> 
    <HostId>{HostId}</HostId> 
</Error> 
+0

Können Sie den Antworttext erfassen, dass '400 Bad Request' Reaktion begleitet? Es sollte etwas menschenlesbares XML mit einem Hinweis geben, der uns hilft, herauszufinden, was gerade passiert. Ansonsten ist es nur Vermutung. –

+0

Der Hauptkommentar mit dieser Information wurde aktualisiert. – Mervill

+0

Danke für das Update. Wir müssen etwas weniger redaktionell sehen, vermute ich. Nichts in einer vor-signierten URL oder der Fehlerantwort ist wirklich sensibel - die RequestId und die HostId sind nur Werte, die die AWS-Unterstützung verwenden kann, um Fehler in ihren Protokollen zu recherchieren, sodass diese nicht angezeigt werden müssen (aber nicht sensitiv sind)), und wenn Sie die accesskeyid (normalerweise beginnt mit A * IA) entfernen möchten, könnten Sie das aus der URL entfernen ... aber wir müssen wahrscheinlich den Rest der URL und Antwort sehen. –

Antwort

2

Das Problem ist, dass HttpURLConnection leise Content-Type: application/x-www-form-urlencoded auf die Anfrage hinzufügt. Dies ist ärgerlich, da es nicht einfach ist zu bestimmen, welche Header in der Anfrage eines Objekts HttpURLConnection sind.

Wie auch immer. Hier ist der richtige Code

uri = new URL(oneTimeUploadUrl); 

// Setup Connection 
HttpsURLConnection http = (HttpsURLConnection) uri.openConnection(); 
http.setDoOutput(true); 
http.setRequestMethod("PUT"); 
http.setRequestProperty("Content-Type"," "); // remove Content-Type header 

// Write Data 
OutputStream os = http.getOutputStream(); 
os.write(_bytes); 
os.flush(); 
os.close(); // request gets sent off to the server 

Siehe auch: HttpURLConnection PUT to Google Cloud Storage giving error 403

Verwandte Themen