ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.38k stars 1.64k forks source link

Redirect to gateway api #730

Closed redplane closed 5 years ago

redplane commented 5 years ago

Expected Behavior / New Feature

When I make request to ocelot gateway, I want the request to be redirected to the api comes from controller in Ocelot.

Actual Behavior / Motivation for New Feature

404 Not found returned.

Steps to Reproduce the Problem

  1. Configure ocelot.json
{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/gateway/survey",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 51981
        }
      ],
      "UpstreamPathTemplate": "/api/survey-gateway",
      "UpstreamHttpMethod": [ "Get" ]
    }
  ]
}
  1. Make request to http://localhost:51981/api/survey-gateway

(http://localhost:51981/api/gateway/survey) is the address of GatewayController in Gateway API.

Specifications

margaale commented 5 years ago

The request should be made to http://localhost/api/survey-gateway according to your config...

philproctor commented 5 years ago

Agreed with Margaale -- I think you are bypassing Ocelot and going directly to the downstream host unless there is something I am missing here.

redplane commented 5 years ago

I tried, but got NotFound status. Here is my postman request:

not-found

And here is my output in asp.net core:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:51981/api/survey-gateway  
Ocelot.Errors.Middleware.ExceptionHandlerMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: ocelot pipeline started
Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: Upstream url path is /api/survey-gateway
Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: downstream templates are /api/gateway/survey
Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware:Information: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: EndpointRateLimiting is not enabled for /api/gateway/survey
Ocelot.Authentication.Middleware.AuthenticationMiddleware:Information: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: No authentication needed for /api/survey-gateway
Ocelot.Authorisation.Middleware.AuthorisationMiddleware:Information: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: /api/gateway/survey route does not require user to be authorised
Ocelot.DownstreamUrlCreator.Middleware.DownstreamUrlCreatorMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: Downstream url is http://localhost:51981/api/gateway/survey
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:51981/api/gateway/survey  0
Ocelot.Errors.Middleware.ExceptionHandlerMiddleware:Debug: requestId: 0HLJH6V6LNJI1:00000004, previousRequestId: no previous request id, message: ocelot pipeline started
Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware:Debug: requestId: 0HLJH6V6LNJI1:00000004, previousRequestId: no previous request id, message: Upstream url path is /api/gateway/survey
Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware:Warning: requestId: 0HLJH6V6LNJI1:00000004, previousRequestId: no previous request id, message: DownstreamRouteFinderMiddleware setting pipeline errors. IDownstreamRouteFinder returned Error Code: UnableToFindDownstreamRouteError Message: Unable to find downstream route for path: /api/gateway/survey, verb: GET
Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware:Warning: requestId: 0HLJH6V6LNJI1:00000004, previousRequestId: no previous request id, message: Unable to find downstream route for path: /api/gateway/survey, verb: GET
Ocelot.Responder.Middleware.ResponderMiddleware:Warning: requestId: 0HLJH6V6LNJI1:00000004, previousRequestId: no previous request id, message: Error Code: UnableToFindDownstreamRouteError Message: Unable to find downstream route for path: /api/gateway/survey, verb: GET errors found in ResponderMiddleware. Setting error response for request path:/api/gateway/survey, request method: GET
Ocelot.Errors.Middleware.ExceptionHandlerMiddleware:Debug: requestId: 0HLJH6V6LNJI1:00000004, previousRequestId: no previous request id, message: ocelot pipeline finished
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 39.3506ms 404 
Ocelot.Requester.Middleware.HttpRequesterMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: setting http response message
Ocelot.Responder.Middleware.ResponderMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: no pipeline errors, setting and returning completed response
Ocelot.Errors.Middleware.ExceptionHandlerMiddleware:Debug: requestId: 0HLJH6V6LNJI2:00000003, previousRequestId: no previous request id, message: ocelot pipeline finished
margaale commented 5 years ago

Do not use por 51891 that's the API port, your gateway port is different, probably 80 if you didn't touch the defaults

margaale commented 5 years ago

Wait, are you running your api and the gateway in the same app?

redplane commented 5 years ago

http://localhost/api/survey-gateway

I tried sending the request to this url, but of course, it is 404, because I'm running the web application in DEBUG mode of Visual Studio 2017.

My API & my gateway are different projects. But for now, I just want to redirect the request to gateway to another url in the same gateway. Let say, I have 1 end-points in **gateway***

http://localhost:51981/api/gateway/survey

And I dont want to expose that api from client, therefore, I configure an Upstream end-point, such as:

http://localhost:51981/api/survey-gateway

That means, in POSTMAN, when I make request to http://localhost:51981/api/survey-gateway, my request will be transparently redirected to http://localhost:51981/api/gateway/survey.

For now, it is 404, not found.

margaale commented 5 years ago

Could you post your configuration file with all the routes?

redplane commented 5 years ago

This is my GateWayController.cs

[Route("api/gateway")]
    public class GatewayController : Controller
    {
        #region Properties

        private readonly IHubContext<GatewayHub> _hubContext;
        #endregion

        #region Constructor

        public GatewayController()
        {

        }

        #endregion

        #region Methods

        /// <summary>
        /// Load survey details.
        /// </summary>
        /// <returns></returns>
        [HttpGet("survey")]
        public async Task<IActionResult> LoadSurveyDetailAsync()
        {
            return Ok();
        }

        #endregion
    }

This is my Startup.cs

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOcelot();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseOcelot().Wait();
            app.UseMvc();
        }
    }

My ocelot.json

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/api/gateway/survey",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 51981
        }
      ],
      "UpstreamPathTemplate": "/api/survey-gateway",
      "UpstreamHttpMethod": [ "GET" ]
    }
  ]
}
margaale commented 5 years ago

And program.cs please

redplane commented 5 years ago

And program.cs please

Here you are, my program.cs

public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args)
        {
            return WebHost
                .CreateDefaultBuilder(args)
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config
                    .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
                    .AddJsonFile("appsettings.json", true, true)
                    .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
                    .AddJsonFile("ocelot.json")
                    .AddEnvironmentVariables();
                })
                .UseStartup<Startup>();
        }
    }
margaale commented 5 years ago

Ohh. I see. Unless I'm mistaken this can't be achieved. Both Middlewares are final in the pipeline. @philproctor what do you think? Can we modify the code to allow ocelot call the next Middleware if the route isn't found in the configuration? Just an idea, I haven't inspect that part of the code yet

philproctor commented 5 years ago

No need for that -- the ordering is controlled by Configure() and ConfigureServices() in Startup.cs -- MVC will continue the pipeline if no controller handles the request. Ocelot is intended to be the last middleware in the chain.

@redplane your code will work if you move AddMvc() and UseMvc() to before AddOcelot() and UseOcelot() respectively in your Startup.cs

margaale commented 5 years ago

You are absolutly correct. I was trying to achive that with nancy and was not able to... Sorry for the confusion. @redplane your startup.cs should look like:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {            
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddOcelot();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
        app.UseOcelot().Wait();
    }
}
philproctor commented 5 years ago

Safe to close this issue?

margaale commented 5 years ago

I would say so. But I was waiting for his confirmation

On Fri, Jan 4, 2019, 19:55 Phil Proctor <notifications@github.com wrote:

Safe to close this issue?

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/ThreeMammals/Ocelot/issues/730#issuecomment-451593385, or mute the thread https://github.com/notifications/unsubscribe-auth/AT1ONjVTJzTdMtmwckV3sWftVbNJpCH6ks5u_9vkgaJpZM4Zkz7L .

redplane commented 5 years ago

Thank you for your help. After having done what @margaale said, I can access the api/gateway/survey through api/survey-gateway.

This issue can be closed now :).