2015-12-10 11 views
11

Ich baue eine API, die von Lambda-Funktionen bedient wird, aber ich brauche diese asynchron zu sein, anstatt das API-Gateway direkt mit der Lambda-Funktion zu verbinden. Ich benutze den "AWS Service Proxy "zu veröffentlichen SNS-Nachrichten und dann haben Sie die Lambda-Funktion abonnieren Sie die relevanten SNS Thema, so dass es die Lieferung der Anfragen empfängt. Hier ist ein Bild, das den Fluss zeigt:AWS API-Gateway kommuniziert mit SNS

enter image description here

ich getestet habe sowohl die Lambda-Funktion in Isolation als auch pub/Sub-Nachrichten zwischen SNS und Lambda, aber ich habe Schwierigkeiten mit dem API-Gateway SNS-Handoff. Die Dokumentation ist ziemlich leicht, aber was ich gehe davon ist jetzt, dass die folgenden Attribute in der POST-Anforderung gesendet werden muss:

  1. Aktion: der API-Gateway bietet diese in der Benutzeroberfläche festgelegt und ich habe setzen in den Aktion veröffentlichen, die

  2. Nachricht die entsprechenden SNS Aktion ist: der Körper der POST-Meldung ein JSON-Dokument sein sollte. Es würde vom Webclient übergeben und über das Gateway an SNS weitergeleitet.

  3. TopicArn: gibt das SNS-Thema an, zu dem wir veröffentlichen. In meinem Entwurf wäre dies ein statischer Wert/Endpunkt, also würde ich bevorzugen, dass der Web-Client dies auch nicht passieren muss, aber wenn es einfacher wäre, dies zu tun, wäre das auch in Ordnung.

Ich habe viele Dinge ausprobiert, bin aber nur stecken. Würde gerne ein gutes Codebeispiel irgendwo finden, aber jede Hilfe würde geschätzt werden.


Wollte ein wenig mehr Kontext auf meinem aktuellen Versuch hinzuzufügen:

ich meine API veröffentlichen und mit Postman versucht haben, um zu versuchen, eine gültige Antwort zu erhalten. Hier ist der Postbote Bildschirme (einer für Kopf Vars, eine für JSON Körper):

header variables json body

Daraus ergibt sich die folgende Fehlermeldung:

{ 
    "Error": { 
    "Code": "InvalidParameter", 
    "Message": "Invalid parameter: TopicArn or TargetArn Reason: no value for required parameter", 
    "Type": "Sender" 
    }, 
    "RequestId": "b33b7700-e8a3-58f7-8ebe-39e4e62b02d0" 
} 

der Fehler scheint darauf hinzudeuten, dass die TopicArn Parameter wird nicht an SNS gesendet, aber ich habe Folgendes in das API-Gateway aufgenommen:

enter image description here

+0

Konnten Sie das jemals lösen? Ich stoße auf ähnliche Probleme mit genau der gleichen Architektur. Bevor ich eine separate Frage über meine Probleme veröffentlichte, dachte ich mir, dass ich sehen würde, ob es dir gelingen würde, das funktionieren zu lassen. – AlexGad

+1

Uh oh. Ich hatte eine Antwort geschrieben, aber es ging nicht durch. Ich werde versuchen, morgen dazu zu kommen. – ken

+0

Haben Sie es geschafft, dies mit POST-Anfragen auszuführen? Die einzige Möglichkeit, dies zu tun, ist das Setzen von TopicArn und Message als Abfrage-String-Parameter (wie die unten stehende Antwort), weil der Anfragetext immer ignoriert wurde, obwohl ich die POST-Methode eingestellt habe. Ich brauche jedoch, was in der Anfrage Körper ist und es scheint, es gibt keine Möglichkeit, ich kann es als Abfrage String-Parameter kopieren. – nanestev

Antwort

5

Ich habe schließlich das bekommen, nachdem sie mit AWS Unterstützung arbeiten zu arbeiten. Hier ist meine Lösung:

  • Zunächst einmal, obwohl Sie eine POST sind Senden Sie nicht Lage sein, eine JSON-Nachricht im Körper der Nachricht zu senden, wie Sie
  • Stattdessen erwarten Sie müssen URL Encode die JSON und gibt es als Abfrageparameter
  • Denken Sie auch daran, dass die JSON Sie sollte mit einem Wurzelobjekt default beginnen senden, die in SNS-Welt bedeutet den „Standardkanal“
  • Dann schließlich nimmt Lambda das SNS-Ereignis auf Sie müssen auch eine Menge Lärm abstrahieren, um an Sie heranzukommen r JSON-Nachricht.Dazu habe ich die folgende Funktion, die ich in meiner Lambda-Funktion:

/** 
 
* When this is run in AWS it is run "through" a SNS 
 
* event wconfig.ich adds a lot of clutter to the event data, 
 
* this tests for SNS data and normalizes when necessary 
 
*/ 
 
function abstractSNS(e) { 
 
    if (e.Records) { 
 
    return JSON.parse(decodeURIComponent(e.Records[0].Sns.Message)).default; 
 
    } else { 
 
    return e; 
 
    } 
 
} 
 

 
/** 
 
* HANDLER 
 
* This is the entry point for the lambda function 
 
*/ 
 
exports.handler = function handler(event, context) { 
 
    parent.event = abstractSNS(event);

+0

Hallo, kannst du einige Details deiner Lösung angeben, wie viel Teil musst du ändern/welcher Teil unterscheidet sich von der normalen Einstellung? Ich habe dieses Problem für die letzten 2 Tage und steckte fest. Problem ist, ich bin nicht klar mit der Lösung, die Sie oben gegeben haben. Danke im Voraus. –

+0

@WilliamFrancisGomes nicht sicher, was noch hinzuzufügen ... die "Handler" -Funktion gibt Ihnen ein "Ereignis" -Objekt, aber wenn Sie SNS verwenden, um das Ereignis auszulösen, erhalten Sie das vollständige SNS-Ereignis. Für mich sind die SNS-Details nicht sehr nützlich außer für das, was in den e.Records [0] .Sns.Message ist, so dass die obige Funktion den Teil auspackt, der mir wichtig ist. – ken

+0

Beachten Sie, dass das API-Gateway jetzt eine direkte Möglichkeit zum Aufrufen von Lambda bietet und es asynchron aufrufen kann, sodass Sie SNS in manchen Fällen nicht ** benötigen. – ken

1

Sie können das API-Gateway verwenden, um Ihre Lambda-Funktion asynchron aufzurufen, indem Sie es als AWS-Service-Proxy konfigurieren. Die Konfiguration ist im Grunde das gleiche Sie in this GitHub sample sehen, mit der Ausnahme, dass die uri für die Lambda-Aufruf Änderungen /invoke-async/ statt nur/aufrufen/

+0

Ich bin ein wenig verwirrt von Ihrem Beispiel. Wohin geht dieses YAML? Kann API-Gateway Swagger-Definitionen importieren? – ken

+0

Beachten Sie auch, dass invoke-Asynchron veraltet ... sie empfehlen aufrufen statt (ich glaube, es ein Parameter es aber Asynchron gesetzt ist) – ken

+0

Ist es möglich, eine Swagger YAML Definition für eine API-I-Setup die Benutzeroberfläche verwenden zu exportieren? Wäre schön, es in YAML-Form statt nur in der Benutzeroberfläche zu sehen. – ken

1

Ich bin nur spekulieren (haben diese selbst nicht versucht), aber ich denke, Sie senden die Nachricht nicht richtig ...

Basierend auf AWS in der Dokumentation hier (http://docs.aws.amazon.com/sns/latest/api/API_Publish.html), müssen Sie in der Nachricht schreiben, was die application/x-www-form-urlencoded Codierung so zu sein scheint:

POST http://sns.us-west-2.amazonaws.com/ HTTP/1.1 
... 
Action=Publish 
&Message=%7B%22default%22%3A%22This+is+the+default+Message%22%2C%22APNS_SANDBOX%22%3A%22%7B+%5C%22aps%5C%22+%3A+%7B+%5C%22alert%5C%22+%3A+%5C%22You+have+got+email.%5C%22%2C+%5C%22badge%5C%22+%3A+9%2C%5C%22sound%5C%22+%3A%5C%22default%5C%22%7D%7D%22%7D 
&TargetArn=arn%3Aaws%3Asns%3Aus-west-2%3A803981987763%3Aendpoint%2FAPNS_SANDBOX%2Fpushapp%2F98e9ced9-f136-3893-9d60-776547eafebb 
&SignatureMethod=HmacSHA256 
&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE 
&SignatureVersion=2 
&Version=2010-03-31 
&Signature=vmqc4XRupKAxsDAdN4j4Ayw5LQljXMps3kss4bkDfCk%3D 
&Timestamp=2013-07-18T22%3A44%3A09.452Z 
&MessageStructure=json 

Das heißt, sieht der Nachrichtentext die Art und Weise ein Browser kodieren würde Formulardaten. Ihre Nachricht kann JSON-formatiert sein, muss aber dennoch so codiert werden, als wäre es ein Formularfeld (eine peinliche Analogie :)).

Auf der Grundlage der allgemeinen Parameter Dokumentation (http://docs.aws.amazon.com/sns/latest/api/CommonParameters.html) haben Sie eine Reihe von zusätzlichen erforderlichen Feldern (der übliche Zugangsschlüssel, Unterschrift und so weiter).

Sie haben nicht angegeben, in welcher Sprache Sie Ihr API-Gateway schreiben. Möglicherweise gibt es dafür ein AWS-SDK, anstatt zu versuchen, die REST-Anforderungen manuell zu erstellen.

+0

WRT zu Sprache, die Lambda-Funktionen am Ende dieses Flusses sind Knoten JS, der aufrufende Webclient ist ein JS SPA (EmberJS). Dazwischen - wo die Nachrichtentransformation stattfindet - ist alles nur eine API-Gateway-Konfiguration. – ken

+0

Die Beispielnachricht, die Sie angegeben haben, sieht wie seine urlencodierte aus, das obige Beispiel schien darauf hinzudeuten, dass Sie JSON in die Nachricht einfügen könnten (zumindest so habe ich es gelesen). – ken

+0

Auch ich gehe davon aus, dass die Unterzeichnung und die entlang der Access Key alle von der API-Gateway-behandelt wird wie die „Konfiguration nur“ Ansatz würde brechen scheinen sie zu fördern werden (und die Benutzeroberfläche für die Ausführung arn fragt) – ken

4

Ich bin vom Api Gateway-Team.

Ich glaube, es gibt ein paar Formate für die HTTP-Anfrage an die API veröffentlichen sind, aber hier ist die, die ich zum ersten Mal verwendet:

AWS-Region us-west-2

AWS-Service sns

AWS Subdomäne

HTTP-Methode POST

Aktion veröffentlichen

== Query-Strings ==

Betreff 'foo'
Nachricht 'bar'
TopicArn 'arn: aws: sns: us-west-2: xxxxxxxxxxxx: Test-api'

Das funktionierte für mich, um eine Nachricht zu veröffentlichen.

Lassen Sie mich wissen, wenn Sie weitere Probleme haben.

Jack

0

ich tun würde, es mag:

WebApp -> Gateway -> Lambda (verwenden Sie Boto3 in SNS veröffentlichen) -> SNS -> Lambda

ich denke, die Dinge einfacher sein.

+0

Können Sie etwas mehr erklären? – abhiarora

+0

Okay, wir verbinden Gateway mit Lambda. nach doc: https://cloudonaut.io/create-a-serverless-restful-api-with-api-gateway-cloudformation-lambda-and-dynamodb/ und dann http: //boto3.readthedocs verwenden.io/de/latest/reference/services/sns.html # SNS.Client.publish ..... um Lambda mit SNS zu verbinden –

+0

Lassen Sie mich wissen, ob dies hilft oder ich werde mit Bildern posten ,, Nur etwas wird dies nutzen Python –

Verwandte Themen