All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.servicecomb.provider.springmvc.reference.CseClientHttpRequest Maven / Gradle / Ivy

There is a newer version: 0.5.0
Show newest version
/*
 * Copyright 2017 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.servicecomb.provider.springmvc.reference;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;

import io.netty.handler.codec.http.QueryStringDecoder;
import io.servicecomb.common.rest.RestConst;
import io.servicecomb.common.rest.codec.LocalRestServerRequest;
import io.servicecomb.common.rest.codec.RestServerRequest;
import io.servicecomb.common.rest.definition.RestOperationMeta;
import io.servicecomb.common.rest.definition.RestParam;
import io.servicecomb.common.rest.locator.OperationLocator;
import io.servicecomb.common.rest.locator.ServicePathManager;
import io.servicecomb.core.Invocation;
import io.servicecomb.core.definition.MicroserviceMeta;
import io.servicecomb.core.invocation.InvocationFactory;
import io.servicecomb.core.provider.consumer.InvokerUtils;
import io.servicecomb.core.provider.consumer.ReferenceConfig;
import io.servicecomb.core.provider.consumer.ReferenceConfigUtils;
import io.servicecomb.swagger.invocation.Response;
import io.servicecomb.swagger.invocation.context.InvocationContext;
import io.servicecomb.swagger.invocation.exception.ExceptionFactory;

public class CseClientHttpRequest extends OutputStream implements ClientHttpRequest {

    private static final Logger LOGGER = LoggerFactory.getLogger(CseClientHttpRequest.class);

    private URI uri;

    private HttpMethod method;

    private HttpHeaders httpHeaders = new HttpHeaders();

    private InvocationContext context;

    private Object requestBody;

    public CseClientHttpRequest() {
    }

    public CseClientHttpRequest(URI uri, HttpMethod method) {
        this.uri = uri;
        this.method = method;
    }

    public InvocationContext getContext() {
        return context;
    }

    public void setContext(InvocationContext context) {
        this.context = context;
    }

    /**
     * 不支持,从outputStream继承,仅仅是为了在CseHttpMessageConverter中,将requestBody保存进来而已
     */
    @Override
    public void write(int b) throws IOException {
        throw new Error("not support");
    }

    public void setRequestBody(Object requestBody) {
        this.requestBody = requestBody;
    }

    @Override
    public HttpMethod getMethod() {
        return method;
    }

    @Override
    public URI getURI() {
        return uri;
    }

    @Override
    public HttpHeaders getHeaders() {
        return httpHeaders;
    }

    @Override
    public OutputStream getBody() throws IOException {
        return this;
    }

    @Override
    public ClientHttpResponse execute() throws IOException {
        RequestMeta requestMeta = createRequestMeta(method.name(), uri);

        QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri.getRawSchemeSpecificPart());
        Map> queryParams = queryStringDecoder.parameters();

        Object[] args = this.collectArguments(requestMeta, queryParams);

        // 异常流程,直接抛异常出去
        return this.invoke(requestMeta, args);
    }

    /**
     * 处理调用URL
     * URL格式:cse://microserviceName/业务url
     */
    private RequestMeta createRequestMeta(String httpMetod, URI uri) {
        String microserviceName = uri.getAuthority();
        ReferenceConfig referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName);

        MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta();
        ServicePathManager servicePathManager = ServicePathManager.getServicePathManager(microserviceMeta);
        if (servicePathManager == null) {
            throw new Error(String.format("no schema defined for %s:%s",
                    microserviceMeta.getAppId(),
                    microserviceMeta.getName()));
        }

        OperationLocator locator = servicePathManager.locateOperation(uri.getPath(), httpMetod);
        RestOperationMeta swaggerRestOperation = locator.getOperation();

        Map pathParams = locator.getPathVarMap();
        return new RequestMeta(referenceConfig, swaggerRestOperation, pathParams);
    }

    private CseClientHttpResponse invoke(RequestMeta requestMeta, Object[] args) {
        Invocation invocation =
            InvocationFactory.forConsumer(requestMeta.getReferenceConfig(),
                    requestMeta.getOperationMeta(),
                    args);
        invocation.getHandlerContext().put(RestConst.REST_CLIENT_REQUEST_PATH,
                this.uri.getRawPath() + "?" + this.uri.getRawQuery());

        if (context != null) {
            invocation.addContext(context);
        }

        Response response = doInvoke(invocation);

        if (response.isSuccessed()) {
            return new CseClientHttpResponse(response);
        }

        throw ExceptionFactory.convertConsumerException((Throwable) response.getResult());
    }

    protected Response doInvoke(Invocation invocation) {
        return InvokerUtils.innerSyncInvoke(invocation);
    }

    private Object[] collectArguments(RequestMeta requestMeta, Map> queryParams) {
        RestServerRequest mockRequest =
            new LocalRestServerRequest(requestMeta.getPathParams(), queryParams, httpHeaders, requestBody);
        List paramList = requestMeta.getSwaggerRestOperation().getParamList();
        Object[] args = new Object[paramList.size()];
        for (int idx = 0; idx < paramList.size(); idx++) {
            RestParam param = paramList.get(idx);
            try {
                args[idx] = param.getParamProcessor().getValue(mockRequest);
            } catch (Exception e) {
                LOGGER.error("error arguments for operation "
                        + requestMeta.getOperationMeta().getMicroserviceQualifiedName(), e);
                throw new Error(e);
            }
        }

        return args;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy