Ocelot | .NET core API Gateway | Microservice library
kandi X-RAY | Ocelot Summary
Support
Quality
Security
License
Reuse
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here
Ocelot Key Features
Ocelot Examples and Code Snippets
Trending Discussions on Ocelot
Trending Discussions on Ocelot
QUESTION
I'm fairly new to the microservices architecture and hand cranked my own api-gateway which works, but from research realised the value in using Ocelot as a replacment due to the features it brings. Today I created a new empty .NET 6 api-gateway project and using the Ocelot documentation brought in nuget packages needed to set it up. The end game is to use Eureka, but as I don't seem to be able to make it work I have stepped back to using a direct call the docker based microservice first.
Looking at the documentation I think I've follow it to the letter, but when I launch the container it does nothing, I wonder if someone could point me in the right direction.
My program.cs
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
var builder = WebApplication.CreateBuilder(args);
builder.Host.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();
})
.ConfigureServices(s =>
{
s.AddOcelot();
//.AddEureka();
});
var app = builder.Build();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseOcelot().Wait();
app.Run();
my ocelot.json
{
"Routes": [
// drugService API
{
"DownstreamPathTemplate": "/api/TerminologyServices/SearchDrugs/{filter}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "drugservice",
"Port": "80"
}
],
"UpstreamPathTemplate": "/TerminologyServices/SearchDrugs/{filter}",
"UpstreamHttpMethod": [ "Get" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5003"
}
}
'''
ANSWER
Answered 2022-Mar-20 at 08:48Replacing localhost for the container name used by the docker compose yaml in this case web.api.gateway solves this problem.
QUESTION
I'm trying to setup a dotnet micro-service backend with a gateway using Ocelote. Doing this as described, Ocelote provides me with multiple swagger definitions (for each micro-service)
Since the API now has multiple definition, each definition has its own defining json file.
How can i generate the API services and Models using openapi-generator-cli in this case. Previously i only had one definition which i generated with the command below, passing it the published json file directly
openapi-generator-cli generate -g typescript-angular -o ./openapi -i http://localhost:xxxx/swagger/docs/v1/project
Additionally how should those definitions be used? Should the services even be split up like this?
ANSWER
Answered 2022-Feb-19 at 16:30Since there was no fitting tool for my problem or an answer for 6 months, i decided to write an open source tool myself. It is still a WIP but it may already be enough for you, just like it is for my current needs.
Basically what it does is detecting the swagger definitions, generating each of those using the openapi-cli-generator
and then merging all generated files together. At the end there are no duplicate files and a single Configuration.
If you find any bugs or unhandled edge cases please contribute via Github!
brew tap deitsch/angler
brew install angler
EDIT
It also includes a fix for openapi-generator/issues/10864 until an official one is released
QUESTION
bit of a strange question, but I was trying to come up with different ways to get around this.
Let's say I have the following Dictionary:
dict={
'Animal':['Cat', 'Dog', 'Ocelot'],
'Humans':['Jack', 'Jill', 'Frank'],
'Fruit':['Apple', 'Orange', 'Banana']
}
Is there a way to access just the third element of every key? The output being 'Ocelot' 'Frank 'Banana'
I know that the notation for single key is Dictionary(KEY)[ITEM PLACE] but is there a way to do this without specifying the key?
Thanks
ANSWER
Answered 2022-Feb-10 at 21:00Here's one approach.
d = {
'Animal':['Cat', 'Dog', 'Ocelot'],
'Humans':['Jack', 'Jill', 'Frank'],
'Fruit':['Apple', 'Orange', 'Banana']
}
print([d[k][2] for k in d])
Result:
['Ocelot', 'Frank', 'Banana']
QUESTION
This is my first stack overflow question, so if I am presenting something wrong, please let me know. I am pretty new to computer programming, so I just have a small webpage where I am just implementing things that I am learning.
I made a little quiz with random trivia multiple choice questions you can take if you press a button. I am using window prompts to ask the questions and get the answers, and I have all of the questions and answers stored as objects with question/prompt and answer pairs. All of those objects are stored in an array in a variable called shortQuizPrompts. I already have the quiz working and everything, aka., It tells you after every question if you got the answer to that question right or wrong, and it gives you a grade afterwards... I also have it set up so that if you enter an answer that is not "a", "b", "c", or "d", it lets you know that it isnt a valid answer. Those sorts of things.
As of right now, you can choose how many questions long you want the quiz to be out of the 24 total questions I have so far. It just asks the questions in the order that they are stored in the array. For example, you will never be asked the last question in the array if you do not choose for the quiz to be the full 24 questions long. However, I want to make the quiz ask the questions in a random order, while also removing those questions from the array as to not ask the same question multiple times.
I have tried increasing the iterator while looping through the array to a random number from 0 to the length of however many questions they chose. Then checking to see if the iterator was larger than the length of the number of questions they chose, it would decrease the iterator until it found a question that is still in the array that it could ask...
If anyone knows how to go about doing that, it would be great. Sorry for the long question btw. I am pretty new to coding, so this is probably a simple answer, but I digress. I'm pretty sure I did everything right. Thx.
const quizButton = document.getElementById("quiz-button");
/* =========================
Question and answer pairs
=========================
*/
let shortQuizPrompts =
[{prompt: "10 + 10\n(a) 10\n(b) 15\n(c) 20\n(d) 25", answer: "c"},
{prompt: "What status did astronomers downgrade Pluto to in 2006?\n(a) Dwarf Planet\n(b) White Dwarf\n(c) Black Dwarf\n(d) Dwarf Star", answer: "a"},
{prompt: 'What tart fruit has a sweet variety called "Meyer"?\n(a) lime\n(b) lemon\n(c) grapefruit\n(d) dragonfruit', answer: "c"},
{prompt: `What bird lays its eggs in other birds' nests?\n(a) Blue Jay\n(b) Robin\n(c) Eagle\n (d) Cuckoo`, answer: "d"},
{prompt: `What is a female goat called?\n(a) a foe\n(b) a larp\n(c) a nanny\n(d) a maur`, answer:"c"},
{prompt: `What is Eisoptrophobia? \n(a) the fear of mirrors\n(b) the fear of cold temperatures\n(c) the fear of farm animals\n(d) the fear of viruses`, answer: `a`},
{prompt: `Which element of the periodic table is named after the sun?\n(a) slinerium\n(b) helium\n(c) magnesium\n(d) uranium`, answer: `b`},
{prompt: `What color is the octopus blood?\n(a) pink\n(b) light green\n(c) violet\n(d) light blue`, answer: `d`},
{prompt: `What value does the Roman numeral C represent?\n(a) 20\n(b) 50\n(c) 100\n(d) 200`, answer: `c`},
{prompt: `What is measured in fathoms?\n(a) depth of water \n(b) sound \n(c) pressure \n(d) light`, answer: `a`},
{prompt: `What is Chiroptophobia?\n(a) fear of plants \n(b) fear of insects\n(c) fear of chirogenics \n(d) fear of bats`, answer: `d`},
{prompt: `What is the longest and heaviest bone in the human body?\n(a) tibia\n(b) skull\n(c) femur\n(d) humorous`, answer: `c`},
{prompt: `What are the two major elements making up the sun?\n(a) hydrogen and helium\n(b) nitrogen and hydrogen\n(c) oxygen and nitrogen\n(d) oxygen and hydrogen`, answer: `a`},
{prompt: `What is poliosis?\n(a) a disease impacting your balance\n(b) graying of hair\n(c) loss of hair\n(d) high potassium pressence in blood`, answer: `b`},
{prompt: `When held to ultraviolet light, what animal’s urine glows in the dark?\n(a) lemur\n(b) cat\n(c) dog\n(d) lamb`, answer: ``},
{prompt: `What year did the "ILOVEYOU" virus began infecting computers worldwide?\n(a) 2000\n(b) 2001\n(c) 2002\n(d) 2004`, answer: `a`},
{prompt: `What planet's four largest moons are collectively known as the Galilean Moons?\n(a) neptune\n(b) jupiter\n(c) saturn\n(d) uranus`, answer: `b`},
{prompt: `What North American mammal is also known as the prairie wolf or brush wolf?\n(a) brown bears\n(b) ocelots\n(c) coyotes\n(d) hyenas`, answer: `c`},
{prompt: `How often are brain cells replaced?\n(a) once every few hours\n(b) once every few days\n(c) once every few weeks\n(d) never`, answer: `d`},
{prompt: `What physical property of a diamond do carats measure?\n(a) mass\n(b) purity \n(c) color quality\n(d) mineral composition`, answer: `a`},
{prompt: `Nosocomephobia is the fear of what?\n(a) night time\n(b) very large objects\n(c) hospitals\n(d) loud noises`, answer: `c`},
{prompt: `In what year did the Soviet Union launch its first Sputnik satellite?\n(a) 1049\n(b) 1957\n(c) 1963\n(d)1972`, answer: `b`},
{prompt: `What is measured in Ergs?\n(a) Work\n(b) mass\n(c) depth\n(d) emotion`, answer: `a`},
{prompt: `What does a Scoville unit measure?\n(a) sourness\n(b) pain\n(c) spiciness\n(d) taste`, answer: `c`},];
/* ======================
initiation of the quiz
======================
*/
quizButton.onclick = () => {
let correct = 0;
const amountOfQuestions = prompt(`How many questions do you want? There are ${shortQuizPrompts.length} maximum`);
alert('You are about to start the quiz. \nFor each question, enter either "a", "b", "c", or "d". \nPress enter to continue');
for(i = 0; i< amountOfQuestions; i++) {
const answer = prompt(shortQuizPrompts[i].prompt);
if(answer === shortQuizPrompts[i].answer && answer !== null && answer !== undefined) {
alert("Correct");
correct++;
} else if (answer !== shortQuizPrompts[i].answer && answer !==null && answer !== undefined && answer.length >= 1 && (answer === "a" || answer === "b" || answer === "c" || answer === "d")) {
alert("Incorrect");
} else if (answer === null) {
alert(`Bruh, why'd you start the quiz if you didnt want to answer the questions lol`);
} else if (answer.length == 0) {
setInterval(alert("Trying to skip questions, I see?? Yeah, you thought you weren't gonna get caught, huh? Well think again")), 100;
}
console.log(answer)
if(i === amountOfQuestions - 1 && (Math.floor(correct / amountOfQuestions * 100)) <= 33) {
alert(`Wow, you're bad! You made a ${Math.floor((correct / amountOfQuestions) * 100).toFixed(2)}% getting ${correct} out of ${amountOfQuestions} questions correct!`);
}
if(i === amountOfQuestions - 1 && (Math.floor(correct / amountOfQuestions * 100)) > 33 && (Math.floor(correct / amountOfQuestions * 100)) <= 66) {
alert(`You did ok. You made a ${Math.floor((correct / amountOfQuestions) * 100).toFixed(2)}% getting ${correct} out of ${amountOfQuestions} questions right!`);
}
if(i === amountOfQuestions - 1 && (Math.floor(correct / amountOfQuestions * 100)) > 66 ) {
alert(`Congratulations! 🎉 You made a ${Math.floor((correct / amountOfQuestions) * 100).toFixed(2)}% getting ${correct} out of ${amountOfQuestions} questions right!`);
}
if(answer !== "a" && answer !== "b" && answer!== "c" && answer !== "d" && answer.length > 0 && answer !== null && answer !== undefined) {
alert(`What are you doing? I told you to only enter "a", "b", "c", or "d" as answers`);
}
}
}
* {
box-sizing: border-box;
}
button {
cursor: pointer;
}
#quiz-text {
position: relative;
left: 42vw;
top: 25vh;
transform: translateX(-2%) translateY(5%);
font-size: 1.5rem;
}
#quiz-button {
position: relative;
left: 45vw;
top: 25vh;
transform: translateX(-2%) translateY(5%);
font-size: 20px;
}
Random Stuff
Want to take a short quiz?
START
ANSWER
Answered 2022-Jan-12 at 01:03You can shuffle the shortQuizPrompts
array before starting the quiz. Array shuffle details can be found in this answer.
Random Quiz
Want to take a short quiz?
START
QUESTION
I am using ASP.Net boilerplate architecture for my project and using Ocelot API Gateway.
Without using gateway, I can access signalr successfully from my angular App.
But when I try to access signalr through API Gateway, All requests stay in pending state and get this error
Following is my configuration.json changes for signalr
And following change I made in the Startup.cs file of the gateway.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
if (_ocelotSwaggerConfiguration.IsSwaggerEnabled)
{
app.UseSwaggerForOcelotUI(Configuration);
}
// Enable ReDoc Documentation
app.UseReDoc(c =>
{
c.DocumentTitle = "AI API";
c.SpecUrl = "/swagger/docs/v1/pitch-ai";
c.RoutePrefix = string.Empty;
c.IndexStream = () => Assembly.GetExecutingAssembly()
.GetManifestResourceStream("AI.Api.Gateway.api_docs.ui.index.html");
c.HeadContent = GetRedocHeaderContent();
});
app.UseAuthentication();
app.UseStaticFiles();
app.UseMetricServer();
app.UseMiddleware();
app.UseHttpMetrics();
app.UseWebSockets();
app.UseHealthChecks("/ready", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("services")
});
app.Map("/switch", appBuilder =>
{
appBuilder.Run(async context =>
{
running = !running;
await context.Response.WriteAsync($"{Environment.MachineName} running {running}");
});
});
app.UseHealthChecks("/health", new HealthCheckOptions
{
Predicate = r => r.Name.Contains("health")
});
app.UseMetricsAllEndpoints();
app.UseOcelot().ContinueWith(t => Log.Error(t.Exception.Message, t.Exception), System.Threading.Tasks.TaskContinuationOptions.OnlyOnFaulted);
}
ANSWER
Answered 2021-Dec-28 at 08:53The following change works for me. Applied following changes in configuration.json
{
"DownstreamPathTemplate": "/{everything}",
"DownstreamScheme": "ws",
"UpstreamPathTemplate": "/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE", "OPTIONS" ],
"SwaggerKey": "ai",
"ServiceName": "ai-web-api",
"RateLimitOptions": {
"ClientWhitelist": [],
"EnableRateLimiting": true,
"Period": "1s",
"PeriodTimespan": 1,
"Limit": 10
}
}
Also, I found that I don't need Microsoft.AspNetCore.SignalR.Client in gateway project.
And I moved app.UseWebSockets();
before app.UseOcelot()
in Startup.cs
QUESTION
I have created two projects one the API Gateway that uses this JSON file:
{
"Routes": [
{
"DownstreamPathTemplate": "/api/post",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44309
}
],
"UpstreamPathTemplate": "/gateway/post",
"UpstreamHttpMethod": [
"POST",
"PUT",
"GET"
]
}
]
}
And on the Microservice side the other project i have created a PostController that inherits Controllerbase, basically an ApiController:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using PostService.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PostService.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PostController : ControllerBase
{
private readonly IPostRepository _postRepository;
public PostController(IPostRepository postRepository)
{
_postRepository = postRepository;
}
[HttpGet]
public IActionResult Get()
{
var posts = _postRepository.GetPosts();
return new OkObjectResult(posts);
}
}
}
When I run the project Two browsers open, the first which is the ApiGateway and the other browser is where the microservice runs on localhost on port 44309. I run this in the address bar for the api gateway:
https://localhost:44342/gateway/post
The great thing is that the Get Method in my PostController get called and returns the data correctly.
But if I wanted to run or deploy these projects on windows server, how would this work on a windows server. What would I need to change in my ocelot.json file or does this remain the same or do O need to change these values to the remote IP and port:
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44309
}
],
So could someone point me in the right direction on how to deploy this on a windows server so that maybe a web or mobileapp can access the APIGateway?
ANSWER
Answered 2021-Dec-27 at 08:20To deploy it on a Windows Server you need to create two web sites on IIS, one for the API Gateway and one for the microservice. The API gateway site should listen on https port 443 and any IP address. The microservice can listen in any port of your choice, but there is no need to configure it for https because the communication between the gateway and the microservice is local to the server. The microservice should listen only on 127.0.0.1 and [::1] IP addresses because the microservice should only be accessed though the API gateway. So your ocelot.json can be:
{
"Routes": [
{
"DownstreamPathTemplate": "/api/post",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44309
}
],
"UpstreamPathTemplate": "/gateway/post",
"UpstreamHttpMethod": [
"POST",
"PUT",
"GET"
]
}
]
}
Don't forget to configure the microservice site bindings for http on port 44309 or the port of your choice
QUESTION
I have two microservices that require access to IWindowsPrincipal of the calling user. I am writing an API Gateway using .Net Core 3.1 that will act as a reverse proxy for these services. I have configured Authentication and Authorization in the API Gateway as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("All allowed",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
services.AddAuthorization();
services.AddControllers();
services.AddHttpForwarder();
services.AddOcelot();
services.AddSwaggerForOcelot(_configuration);
}
public void Configure(IApplicationBuilder app)
{
app.UseCors("All allowed");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSwaggerForOcelotUI(options =>
{
options.PathToSwaggerGenerator = "/swagger/docs";
});
app.UseOcelot();
}
I would like to access the calling user's identity using HttpContext.User.Identity in the method of the microservices.
Actual ResultIn the methods of the microservices, HttpContext.User.Identity.IsAuthenticated is false and the identity information is empty.
QuestionIs there a way to configure Ocelot in the gateway so that it will Challenge the caller if necessary receive Windows Authentication information and pass it on to the microservices? If this is not possible, is the recommend way to achieve my goal, to perform implement Windows Authentication in each of the microservices? Isn't Ocelot supposed to allow me to handle Authentication in one place for all microservices?
Follow on Question 1Ocelot's documentation refers to Authentication using a JWT. Should I conclude that Ocelot only provides JWT configuration?
Follow on Question 2I have read a little about Yarp (https://microsoft.github.io/reverse-proxy/) Should I be using Yarp instead of Ocelot to achieve my goal?
ANSWER
Answered 2021-Nov-21 at 17:22I thought the answer is No
Is there a way to configure Ocelot in the gateway so that it will Challenge the caller if necessary receive Windows Authentication information and pass it on to the microservices?
The problem is Windows Authentication is stateful, server and client are in the same Active Directory , you can find the note in .NET Core Windows Authentication
Windows Authentication is a stateful scenario primarily used in an intranet, where a proxy or load balancer doesn't usually handle traffic between clients and servers.
Microservices architecture requires a stateless instead stateful (means the server and client are in different AD/OS/Network). And Gateway is a stateless component in Microservices picture.
The only way Ocelot can authenticate Windows User is using Active Directory Federated Services (ADFS) with OpenID Connect (OIDC) or constructing Identity Server in the IIS Server by yourself. You can read the scenario in ADFS or Azure AD for more details.
Beside, there are my answers for two following questions:
- No, Ocelot just provides the add-in feature to detect which claims of JWT must be included before it allows the request to go through downstream. You can build the custom Authentication/Authorization middleware to allow/deny the correct upstream.
- No, YARP is the same meaning of Ocelot in your requirement.
QUESTION
I wanna implement JWT
authentication in the Ocelot API gateway, I followed ocelot documentation carefully and also implemented that. But I got an error that not any idea for solving that.
I used this section of the documentation for enabling authentication.
My received error:
System.AggregateException: 'One or more errors occurred. (Unable to start Ocelot, errors are: Authentication Options AuthenticationProviderKey:BaseAuthenticationSchema,AllowedScopes:[] is unsupported authentication provider)'
Used packages:
Ocelot(17.0.0)
Microsoft.AspNetCore.Authentication.JwtBearer(5.0.11)
Also sections of my codes for more specification:
Program.cs:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddJsonFile($"ocelot.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup()
.UseSerilog((_, config) =>
{
config
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File(@"Logs\AllHttpRequestsLog.txt", rollingInterval: RollingInterval.Day);
})
.Configure(app =>
{
app.UseMiddleware();
app.UseOcelot().Wait();
});
});
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Adding Authentication
var baseAuthenticationProviderKey = "BaseAuthenticationSchema";
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(baseAuthenticationProviderKey, options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidAudience = "ValidAudience",
ValidIssuer = "ValidIssuer ",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("IssuerSigningKey"))
};
});
services.AddControllers();
services.AddOcelot(_configuration);
}
And finally used configuration for the ocelot:
{
"DownstreamPathTemplate": "/api/v1/banks",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44371
}
],
"UpstreamPathTemplate": "/api/market/banks",
"UpstreamHttpMethod": [ "Get" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "BaseAuthenticationSchema",
"AllowedScopes": []
}
}
I investigated all articles and also the ocelot GitHub page like this open issue, But my problem was not solved. Can anyone help me?
Thanks a lot.
ANSWER
Answered 2021-Oct-26 at 13:14Finally, I solved my problem using this comment on the Ocelot GitHub page open issues.
Just moved the authentication configuration from the startup.cs
file to the program.cs
file on the .ConfigureServices
section.
Like this:
.ConfigureServices(s =>
{
// Adding Authentication
var baseAuthenticationProviderKey = "BaseAuthenticationSchema";
s.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(baseAuthenticationProviderKey, options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidAudience = "ValidAudience",
ValidIssuer = "ValidIssuer",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret"))
};
});
s.AddOcelot();
})
Also, removed that configuration from the startup.cs
class.
QUESTION
There is an Api Gateway that is configured by ocelot. I want to request to the Api with Kendo object and receive that as a Kendo DataSourceRequest. I just did it in Angular and dot net core Api project and It worked properly. However, in this current project I don't have any idea how can I do that via Ocelot. This is my Api method in this below.
[HttpGet]
public ActionResult User_Read([DataSourceRequest] DataSourceRequest request)
{
var data = _unitOfWork.Repository().GetAll();
return Ok(data.ToList().ToDataSourceResult(request, ModelState));
}
ocelot configuration
{
"DownstreamPathTemplate": "/api/auth/User_Read/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9001
}
],
"UpstreamPathTemplate": "/User_Read/{everything}",
"UpstreamHttpMethod": [ "get" ]
}
and my client request code is like this:
read: function (e) {
if (thisObject.defaultFilter) {
if (e.data.filter) {
var filters = e.data.filter.filters;
var existFilter = filters.filter(function (obj) {
if (obj.field == thisObject.defaultFilter.field) return true;
}).lenght > 0;
if (!existFilter) e.data.filter.filters.push(thisObject.defaultFilter);
}
else {
e.data.filter = { logic: "and", filters: [thisObject.defaultFilter] }
}
}
const params = `${toDataSourceRequestString(e.data)}`;
// datasource read request
thisObject.http.get(thisObject.readUrl + "?" + params).subscribe((res) => {
e.success(res);
});
}
You will find it easy to how send request for reading data in dot net core and angular in kendo grid here
Finally I got the solution on my own. The problem was in Ocelot configuration. I will explain as an answer.
ANSWER
Answered 2021-Sep-24 at 09:44I should have replaced "/api/auth/User_Read/{everything}"
with "/api/auth/User_Read?{url}"
or any name instead of "url" like "everything". The important thing was the "?" for mapping routes in Ocelot.
QUESTION
I'm tring to override Ocelot AuthorizationMiddleware using a OcelotPipelineConfiguration in .NET 5 WebApi. This is my code:
UPDATEDConfigure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAuthorizationService authorizationService)
{
if (env.EnvironmentName == Environments.Development)
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
var configuration = new OcelotPipelineConfiguration
{
AuthorizationMiddleware = async (ctx, next) =>
{
if (! await authorizationService.IsValid(ctx))
{
ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await ctx.Response.WriteAsync("Some Error !");
}
else
{
await next.Invoke();
}
},
};
app.UseOcelot(configuration).Wait();
}
ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
string AuthenticationKey = "AuthenticationKey";
services.AddLogging();
services.AddAuthentication(option =>
{
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(AuthenticationKey, option =>
{
option.RequireHttpsMetadata = true;
option.SaveToken = true;
option.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey =
new SymmetricSecurityKey(
Encoding.ASCII.GetBytes(Configuration.GetSection("SecretKey").Value)),
ValidateIssuerSigningKey = true,
ValidateIssuer = false,
ValidateAudience = false
};
//option.ForwardSignIn
});
services.AddHttpClient();
services.AddScoped();
services
.AddOcelot()
.AddDelegatingHandler();
services.AddMvc();
}
As you can see, in some situations I need to return an immediate response like Unauthorized, but my code always return a 500 Internal Server Error to Postman. I searched a lot and found this question. But I cann't find Errors.Add method in HTTPContext. Is there any Idea to return immediate Unauthorized response?
ANSWER
Answered 2021-Sep-12 at 04:37I found the correct answer by @Artur comment. I replaced
ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await ctx.Response.WriteAsync("Some Error !");
in Configure Method with this one:
ctx.Items.SetError(new UnauthorizedError("your custom message"));
return;
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install Ocelot
Support
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesExplore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits
Save this library and start creating your kit
Share this Page