private void generateOperationSerializerMiddleware()

in codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/integration/HttpBindingProtocolGenerator.java [229:335]


    private void generateOperationSerializerMiddleware(GenerationContext context, OperationShape operation) {
        SymbolProvider symbolProvider = context.getSymbolProvider();
        Model model = context.getModel();
        ServiceShape service = context.getService();
        Shape inputShape = model.expectShape(operation.getInput()
                .orElseThrow(() -> new CodegenException("expect input shape for operation: " + operation.getId())));
        Symbol inputSymbol = symbolProvider.toSymbol(inputShape);
        ApplicationProtocol applicationProtocol = getApplicationProtocol();
        Symbol requestType = applicationProtocol.getRequestType();
        HttpTrait httpTrait = operation.expectTrait(HttpTrait.class);

        GoStackStepMiddlewareGenerator middleware = GoStackStepMiddlewareGenerator.createSerializeStepMiddleware(
                ProtocolGenerator.getSerializeMiddlewareName(operation.getId(), service, getProtocolName()),
                ProtocolUtils.OPERATION_SERIALIZER_MIDDLEWARE_ID);

        middleware.writeMiddleware(context.getWriter().get(), (generator, writer) -> {
            writer.addUseImports(SmithyGoDependency.FMT);
            writer.addUseImports(SmithyGoDependency.SMITHY);
            writer.addUseImports(SmithyGoDependency.SMITHY_HTTP_BINDING);

            // cast input request to smithy transport type, check for failures
            writer.write("request, ok := in.Request.($P)", requestType);
            writer.openBlock("if !ok {", "}", () -> {
                writer.write("return out, metadata, "
                             + "&smithy.SerializationError{Err: fmt.Errorf(\"unknown transport type %T\", in.Request)}"
                );
            });
            writer.write("");

            // cast input parameters type to the input type of the operation
            writer.write("input, ok := in.Parameters.($P)", inputSymbol);
            writer.write("_ = input");
            writer.openBlock("if !ok {", "}", () -> {
                writer.write("return out, metadata, "
                             + "&smithy.SerializationError{Err: fmt.Errorf(\"unknown input parameters type %T\","
                             + " in.Parameters)}");
            });

            writer.write("");
            writer.write("opPath, opQuery := httpbinding.SplitURI($S)", httpTrait.getUri());
            writer.write("request.URL.Path = smithyhttp.JoinPath(request.URL.Path, opPath)");
            writer.write("request.URL.RawQuery = smithyhttp.JoinRawQuery(request.URL.RawQuery, opQuery)");
            writer.write("request.Method = $S", httpTrait.getMethod());
            writer.write("restEncoder, err := httpbinding.NewEncoder(request.URL.Path, request.URL.RawQuery, "
                         + "request.Header)");
            writer.openBlock("if err != nil {", "}", () -> {
                writer.write("return out, metadata, &smithy.SerializationError{Err: err}");
            });
            writer.write("");

            // we only generate an operations http bindings function if there are bindings
            if (isOperationWithRestRequestBindings(model, operation)) {
                String serFunctionName = ProtocolGenerator.getOperationHttpBindingsSerFunctionName(
                        inputShape, service, getProtocolName());
                writer.openBlock("if err := $L(input, restEncoder); err != nil {", "}", serFunctionName, () -> {
                    writer.write("return out, metadata, &smithy.SerializationError{Err: err}");
                });
                writer.write("");
            }

            // Don't consider serializing the body if the input shape is a stubbed synthetic clone, without an
            // archetype.
            if (!CodegenUtils.isStubSyntheticClone(ProtocolUtils.expectInput(model, operation))) {
                Optional<EventStreamInfo> eventStreamInfo = EventStreamIndex.of(model).getInputInfo(operation);

                // document bindings vs payload bindings vs event streams
                HttpBindingIndex httpBindingIndex = HttpBindingIndex.of(model);
                boolean hasDocumentBindings = httpBindingIndex
                        .getRequestBindings(operation, HttpBinding.Location.DOCUMENT)
                        .stream().anyMatch(httpBinding -> eventStreamInfo.map(streamInfo ->
                                !streamInfo.getEventStreamMember().equals(httpBinding.getMember())).orElse(true));

                Optional<HttpBinding> payloadBinding = httpBindingIndex.getRequestBindings(operation,
                                HttpBinding.Location.PAYLOAD).stream()
                        .filter(httpBinding -> eventStreamInfo.map(streamInfo ->
                                !streamInfo.getEventStreamMember().equals(httpBinding.getMember())).orElse(true))
                        .findFirst();

                if (eventStreamInfo.isPresent() && (hasDocumentBindings || payloadBinding.isPresent())) {
                    throw new CodegenException("HTTP Binding Protocol unexpected document or payload bindings with "
                                               + "input event stream");
                }

                if (eventStreamInfo.isPresent()) {
                    writeOperationSerializerMiddlewareEventStreamSetup(context, eventStreamInfo.get());
                } else if (hasDocumentBindings) {
                    // delegate the setup and usage of the document serializer function for the protocol
                    writeMiddlewareDocumentSerializerDelegator(context, operation, generator);

                } else if (payloadBinding.isPresent()) {
                    // delegate the setup and usage of the payload serializer function for the protocol
                    MemberShape memberShape = payloadBinding.get().getMember();
                    writeMiddlewarePayloadSerializerDelegator(context, memberShape);
                }
                writer.write("");
            }

            // Serialize HTTP request with payload, if set.
            writer.openBlock("if request.Request, err = restEncoder.Encode(request.Request); err != nil {", "}", () -> {
                writer.write("return out, metadata, &smithy.SerializationError{Err: err}");
            });
            writer.write("in.Request = request");
            writer.write("");

            writer.write("return next.$L(ctx, in)", generator.getHandleMethodName());
        });
    }