Skip to content

Commit

Permalink
implement awsjson10 request routing
Browse files Browse the repository at this point in the history
  • Loading branch information
lucix-aws committed Jan 29, 2024
1 parent bd26a17 commit fd6b7b4
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ public class TmpCodegenIntegration implements GoIntegration {
public void writeAdditionalFiles(
GoSettings settings, Model model, SymbolProvider symbolProvider, GoDelegator goDelegator
) {
final var service = settings.getService(model);

// TODO should be resolved from model
final var protocolGenerator = new AwsJson10ProtocolGenerator();
final var protocolGenerator = new AwsJson10ProtocolGenerator(model, service, symbolProvider);

final var service = settings.getService(model);
goDelegator.useFileWriter("feat_svcgen.go", settings.getModuleName(), GoWriter.ChainWritable.of(
protocolGenerator.generateSource(),
new ServiceInterface(model, service, symbolProvider),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public GoWriter.Writable generateTransportOptions() {
public GoWriter.Writable generateTransportInit() {
return goTemplate("""
sv.server = &$T{
Handler: &httpHandler{},
Handler: &httpHandler{svc},
}
""", GoStdlibTypes.Net.Http.Server);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,75 @@

import static software.amazon.smithy.go.codegen.GoWriter.goTemplate;

import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.go.codegen.GoStdlibTypes;
import software.amazon.smithy.go.codegen.GoWriter;
import software.amazon.smithy.go.codegen.service.NotImplementedError;
import software.amazon.smithy.go.codegen.service.ServiceInterface;
import software.amazon.smithy.go.codegen.service.protocol.HttpProtocolGenerator;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.TopDownIndex;
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.utils.MapUtils;

/**
* Implements the aws.protocols#awsJson1_0 protocol.
*/
public final class AwsJson10ProtocolGenerator extends HttpProtocolGenerator {
private final Model model;
private final ServiceShape service;
private final SymbolProvider symbolProvider;

public AwsJson10ProtocolGenerator(Model model, ServiceShape service, SymbolProvider symbolProvider) {
this.model = model;
this.service = service;
this.symbolProvider = symbolProvider;
}

@Override
public GoWriter.Writable generateSource() {
return GoWriter.ChainWritable.of(
super.generateSource(),
generateSerializeError()
).compose();
}

private GoWriter.Writable generateSerializeError() {
return goTemplate("""
func serializeError(w $rw:T, err error) {
if _, ok := err.(*$notImplemented:L); ok {
writeEmpty(w, http.StatusNotImplemented)
return
}
writeEmpty(w, http.StatusInternalServerError)
}
func writeEmpty(w $rw:T, status int) {
w.WriteHeader(status)
w.Write([]byte("{}"))
}
""",
MapUtils.of(
"rw", GoStdlibTypes.Net.Http.ResponseWriter,
"notImplemented", NotImplementedError.NAME
));
}

@Override
public GoWriter.Writable generateHttpHandler() {
return goTemplate("""
type httpHandler struct{}
type httpHandler struct{
service $interface:L
}
var _ $handler:T = (*httpHandler)(nil)
$serveHttp:W
""",
MapUtils.of(
"interface", ServiceInterface.NAME,
"handler", GoStdlibTypes.Net.Http.Handler,
"serveHttp", generateServeHttp()
));
Expand All @@ -44,12 +94,57 @@ public GoWriter.Writable generateHttpHandler() {
private GoWriter.Writable generateServeHttp() {
return goTemplate("""
func (h *httpHandler) ServeHTTP(w $rw:T, r $r:P) {
w.WriteHeader(http.StatusTeapot) // TODO
w.Header().Set("Content-Type", "application/x-amz-json-1.0")
if r.Method != http.MethodPost {
writeEmpty(w, http.StatusNotFound)
return
}
target := r.Header.Get("X-Amz-Target")
$route:W
writeEmpty(w, http.StatusNotFound)
}
""",
MapUtils.of(
"rw", GoStdlibTypes.Net.Http.ResponseWriter,
"r", GoStdlibTypes.Net.Http.Request
"r", GoStdlibTypes.Net.Http.Request,
"route", generateRouteRequest()
));
}

private GoWriter.Writable generateRouteRequest() {
return GoWriter.ChainWritable.of(
TopDownIndex.of(model).getContainedOperations(service).stream()
.map(it -> goTemplate("""
if target == $S {
$W
}
""", getOperationTarget(it), generateHandleOperation(it)))
.toList()
).compose(false);
}

private String getOperationTarget(OperationShape operation) {
return service.getId().getName(service) + "." + operation.getId().getName(service);
}

private GoWriter.Writable generateHandleOperation(OperationShape operation) {
return goTemplate("""
w.Header().Set("X-Amz-Target", $target:S)
_, err := h.service.$operation:T(r.Context(), nil)
if err != nil {
serializeError(w, err)
return
}
writeEmpty(w, http.StatusOK)
return
""",
MapUtils.of(
"target", getOperationTarget(operation),
"operation", symbolProvider.toSymbol(operation)
));
}
}

0 comments on commit fd6b7b4

Please sign in to comment.