Leider enthält keiner der Screenshots die gesendeten Header (Response, Reply)
Hast du der Default Route auch eine Funktion hinterlegt?
Leider enthält keiner der Screenshots die gesendeten Header (Response, Reply)
Hast du der Default Route auch eine Funktion hinterlegt?
Hast du der Default Route auch eine Funktion hinterlegt?
Ich beantworte es mir mal selbst, es sieht nicht danach aus, ansonsten sollten diese in den Response Headers auftauchen.
Diese oder ähnliche hätte ich im Response erwartet.
ZitatHast du der Default Route auch eine Funktion hinterlegt?
Wo müsste das getan werden - im LambdaHandler oder in AWS Lamda?
Mein LambdaHandler sieht aktuell so aus:
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
import com.amazonaws.services.simpleemail.model.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
public class LambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {
String path = request.getPath();
String httpMethod = request.getHttpMethod();
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setHeaders(getCORSHeaders()); // Setze CORS-Header
if ("POST".equals(httpMethod) && "/Kontakformular-Emailversand".equals(path)) {
response = handlePostRoute(request);
} else if ("ANY".equals(httpMethod) && path.startsWith("/proxy")) {
response = handleProxyRoute(request);
} else {
response.setStatusCode(404);
response.setBody("{\"message\":\"Route not found\"}");
}
return response;
}
// POST Route bearbeiten
private APIGatewayProxyResponseEvent handlePostRoute(APIGatewayProxyRequestEvent request) {
// JSON body des Requests
String body = request.getBody();
ObjectMapper objectMapper = new ObjectMapper();
String name = "";
String email = "";
String message = "";
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setHeaders(getCORSHeaders()); // Setze CORS-Header
try {
// JSON body parsen
JsonNode rootNode = objectMapper.readTree(body);
name = rootNode.get("name").asText();
email = rootNode.get("email").asText();
message = rootNode.get("message").asText();
} catch (Exception e) {
e.printStackTrace();
response.setStatusCode(400);
response.setBody("{\"message\":\"Invalid input\"}");
return response;
}
String to = "example@hotmail.de";
String from = "examplegmail.com"; // Habe ich in AWS SES verifiziert sein
String subject = "New Contact Form Submission";
String textBody = "Name: " + name + "\nEmail: " + email + "\nMessage: " + message;
try {
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
.withRegion("us-west-2").build();
SendEmailRequest sendEmailRequest = new SendEmailRequest()
.withDestination(new Destination().withToAddresses(to))
.withMessage(new Message()
.withBody(new Body().withText(new Content().withCharset("UTF-8").withData(textBody)))
.withSubject(new Content().withCharset("UTF-8").withData(subject)))
.withSource(from);
client.sendEmail(sendEmailRequest);
response.setStatusCode(200);
// Struktur der Antwort
response.setBody("{\"message\": \"Erfolgreich\"}");
} catch (Exception e) {
e.printStackTrace();
response.setStatusCode(500);
response.setBody("{\"message\":\"Failed to send email\"}");
}
return response;
}
// proxy+ Route bearbeiten
private APIGatewayProxyResponseEvent handleProxyRoute(APIGatewayProxyRequestEvent request) {
// Beispiel-Response für proxy+ Route
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setStatusCode(200);
response.setBody("{\"message\":\"Proxy route handled successfully\"}");
// CORS-Header setzen
response.setHeaders(getCORSHeaders());
return response;
}
//Auskommentiert
/* // Methode zum Erstellen der CORS-Header
private Map<String, String> getCORSHeaders() {
Map<String, String> headers = new HashMap<>();
headers.put("Access-Control-Allow-Headers", "Content-Type");
headers.put("Access-Control-Allow-Origin", "https://adurach.com");
headers.put("Access-Control-Allow-Methods", "OPTIONS,POST,GET");
return headers;
}*/
}
Alles anzeigen
Und hier weiterhin die Headers beim fehlerhaften Befehl:
pasted-from-clipboard.png
Besten Dank dir. Hoffe, du kannst du noch etwa Geduld aufbringen.
Aktuell sieht es für mich so aus, als ob die neue "/{proxy+}" Route nicht mit deinem Lamda Handler verknüpft ist (keine Integration)
Diese Aussage mache ich aufgrund dieses Codeblocks:
...
if ("POST".equals(httpMethod) && "/Kontakformular-Emailversand".equals(path)) {
response = handlePostRoute(request);
} else if ("ANY".equals(httpMethod) && path.startsWith("/proxy")) {
response = handleProxyRoute(request);
} else {
response.setStatusCode(404);
response.setBody("{\"message\":\"Route not found\"}");
}
...
In der Browserkonsole sehen wir im Preflight einen OPTIONS Request, diese sollte damit im else Zweig landen und damit einen Status Code 404 zurücksenden (inkl. Body "Route not found)", dies passiert aber nicht es kommt ein 204 ohne Body zurück.
Nehme wir mal an die Funktion wäre korrekt verknüpft, möchtest du die notwendigen Header eigentlich im else if behandeln, dies wird m.E. aber nicht funktionieren da die Methode OPTIONS und nicht ANY ist.
Selbst wenn der Vergleich funktionieren sollten, sollten wir einen Status Code 200 sehen (inkl. Body "Proxy route handled successfully")
Die auskommentierte Methode getCORSHeaders wird auch nicht dazu beitragen, die richtigen Header an den Browser zurückzusenden.
Stelle sicher das die neue Route auch in deiner Lamda Funktion landet, dann sollte das CORS Problem auch lösbar sein.
Ich habe ANY durch OPTIONS ersetzt und nochmal die Syntax angepasst, damit die Route mit der Schreibweise {proxy+} erkannt wird. Die Methode heißt jetzt handleOptionsRoute statt handleProxyRoute
package lambda;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
import com.amazonaws.services.simpleemail.model.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
public class LambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {
String path = request.getPath();
String httpMethod = request.getHttpMethod();
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setHeaders(getCORSHeaders()); // Setze CORS-Header
if ("POST".equals(httpMethod) && "/Kontakformular-Emailversand".equals(path)) {
response = handlePostRoute(request);
} else if ("OPTIONS".equals(httpMethod) && path.matches("^/.*")){
response = handleOptionsRoute(request);
} else {
response.setStatusCode(404);
response.setBody("{\"message\":\"Route not found\"}");
}
return response;
}
// POST Route bearbeiten
private APIGatewayProxyResponseEvent handlePostRoute(APIGatewayProxyRequestEvent request) {
// JSON body des Requests
String body = request.getBody();
ObjectMapper objectMapper = new ObjectMapper();
String name = "";
String email = "";
String message = "";
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setHeaders(getCORSHeaders()); // Setze CORS-Header
try {
// JSON body parsen
JsonNode rootNode = objectMapper.readTree(body);
name = rootNode.get("name").asText();
email = rootNode.get("email").asText();
message = rootNode.get("message").asText();
} catch (Exception e) {
e.printStackTrace();
response.setStatusCode(400);
response.setBody("{\"message\":\"Invalid input\"}");
return response;
}
String to = "x@hotmail.de";
String from = "x@gmail.com"; // Habe ich in AWS SES verifiziert sein
String subject = "New Contact Form Submission";
String textBody = "Name: " + name + "\nEmail: " + email + "\nMessage: " + message;
try {
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
.withRegion("us-west-2").build();
SendEmailRequest sendEmailRequest = new SendEmailRequest()
.withDestination(new Destination().withToAddresses(to))
.withMessage(new Message()
.withBody(new Body().withText(new Content().withCharset("UTF-8").withData(textBody)))
.withSubject(new Content().withCharset("UTF-8").withData(subject)))
.withSource(from);
client.sendEmail(sendEmailRequest);
response.setStatusCode(200);
response.setBody("{\"message\": \"Erfolgreich\"}");
} catch (Exception e) {
e.printStackTrace();
response.setStatusCode(500);
response.setBody("{\"message\":\"Failed to send email\"}");
}
return response;
}
// OPTIONS Route bearbeiten
private APIGatewayProxyResponseEvent handleOptionsRoute(APIGatewayProxyRequestEvent request) {
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
response.setStatusCode(200);
response.setBody("{\"message\":\"CORS preflight successful\"}");
response.setHeaders(getCORSHeaders()); // CORS-Header setzen
return response;
}
// Methode zum Erstellen der CORS-Header
private Map<String, String> getCORSHeaders() {
Map<String, String> headers = new HashMap<>();
headers.put("Access-Control-Allow-Headers", "Content-Type");
headers.put("Access-Control-Allow-Origin", "https://adurach.com");
headers.put("Access-Control-Allow-Methods", "OPTIONS,POST,GET");
return headers;
}
}
Alles anzeigen
Außerdem habe ich in Lambda für die neue Route eine Integration erstellt, wie schon bei der Route mit POST.
Weiterhin gilt dies:
Das wird ja immer schlimmer ![]()
Ich denke wir sollten noch einmal ein paar Dinge zurückbauen und die Grundfunktionen testen.
Deine Lambda Funktion inkl. des Endpoints solltest du erstmal über eine Tool wie z.B. Postman testen, ob sie auch wirklich tut was du möchtest.
Du einen direkten Aufruf kannst du das CORS Thema erstmal umgeben.
Ich habe mir mal Beispielhaft eine Lambda Funktion erstellt und teste diese mittels Postman.
Lambda Funktion
Im API Gateway (http api) ist nur eine Route definiert.
CORS ist ebenfalls konfiguriert
Wichtig ich nutze keine Authorization, etc.
Bevor ich die Funktion nun so benutze wie sie aus dem Frontend aufgerufen wird, teste ich sie ohne CORS Headers.
Es wird dabei direkt eine POST Request erzeugt.
Nun der nächste Test um die CORS/OPTIONS Funktionalität zu prüfen.
Im CORS Test setze ich zusätzliche Header (vglb. Frontend), wie man sieht fügt AWS beim Response die entsprechenden CORS Header hinzu (die Lambda Funktion ergänzt hier nichts).
Ich kann dir daher nur empfehlen auf die Basic zurückzukehren und mit einer Route zu starten.
Den POST Request würde ich mit geeigneten Daten dann erstmal unabhängig zum Frontend testen (siehe mein POST Request), sollte hier alles klappen geht es weiter mit OPTIONS (hier sollte es ausreichen in deiner Funktion bei OPTIONS einfach einen Status 200 zurückzusenden.
Der Code-Editor im Lambda funktioniert anscheinend für keine Java Runtime, denn ich habe es mit den Versionen 11 und 17 versucht.
pasted-from-clipboard.pngpasted-from-clipboard.png
Es scheint aber, als wäre das Testergebnis hier eh nicht relevant für den Prozess, weil du nicht weiter darauf eingehst.
Ich denke, du wolltest wohl nur den Code der Test-Funktion zeigen.
Also habe ich nun in meinem Projekt weiterhin Java 17 und in Lambda ebenfalls Java 17 als Runtime eingerichtet.
_____
Dann habe ich im Backend-Ordner meines Projekt eine my_lambda_function.js erstellt und gezippt in Lambda hochgeladen. Meine function "Kontaktformular1" wurde entsprechend geupdated.
____
Meine CORS-Einstellungen sind identisch zu deinen, abgesehen von der url, die bei mir meine Seite ist (ohne www).
____
Also eben die URL in Postman getestet, die so auch in meiner entsprechenden Methode im Frontend bisher angeführt hatte:
pasted-from-clipboard.png
___
In Postman erhalte ich dann dieses Ergebnis:
pasted-from-clipboard.png
Alleine das mit Postman wieder ein 404 zurückkommt inkl. „Not found“ ist ein starker Hinweis das der Aufruf nicht in deiner Java Lambdafunktion ankommt.
Woran es liegt ist aus der Ferne schwer zu beurteilen.
Bau doch testhalber mal eine API ähnlich wie mein Beispiel mit z.B node auf und schau ob du damit zum Erfolg kommst.
Gibt es eigentlich einen Grund Java zu verwenden und keine Laufzeitumgebung wie node oder Python?
Bist du bei dem Thema weitergekommen?
Ich kann dir ansonsten gerne mal eine Testfunktion auf AWS zur Verfügung stellen, mit der du die Integration testen kannst.
export const handler = async (event) => {
const method = event.httpMethod;
const body = JSON.parse(event.body);
var returnData = 'Hello from Lambda!';
switch (method) {
case 'OPTIONS':
returnData = 'Hello from Lambda: OPTIONS';
break;
case 'POST':
returnData = {
message: 'Hello from Lambda: POST',
receivedData: body
};
break;
default:
break;
};
const response = {
statusCode: 200,
body: JSON.stringify(returnData),
};
return response;
};
Alles anzeigen
Endpunkt würde ich per PM teilen (aus Gründen
)
Hallo Patrick,
ich habe zwischenzeitlich ein anderes Projekt verfolgen müssen. Nun kann ich mich dieser Sache wieder zuwenden. Ich werde deine Hinweise befolgen - sprich, auch u.a. solch eine Testfunktion erstellen..
Zu deiner Frage zu Java. Ich versuche aktuell bevorzugt mit den mir bekannten Technologien zu arbeiten, um mein Wissen darüber auch gleichzeitig weiter zu vertiefen. Danke dir jedenfalls sehr. Melde mich hier wieder.