From the example given at this place :
https://pub.dev/packages/shelf_router/example
I have written the router part like this :
class Service {
Handler get handler {
final router = Router();
router.get('/say-hi/<name>', (Request request, String name) {
return Response.ok('hi $name');
});
router.get('/user/<userId|[0-9]+>', (Request request, String userId) {
return Response.ok('User has the user-number: $userId');
});
router.get('/wave', (Request request) async {
await Future.delayed(Duration(milliseconds: 100));
return Response.ok('_o/');
});
router.mount('/api/', Api().router);
router.all('/<ignored|.*>', (Request request) {
return Response.notFound('Page not found');
});
return router;
}
}
class Api {
Future<Response> _messages(Request request) async {
return Response.ok('[]');
}
Router get router {
final router = Router();
router.get('/messages', _messages);
router.get('/messages/', _messages);
uter.all('/<ignored|.*>', (Request request) => Response.notFound('null'));
return router;
}
}
and from the main method it tells to use it like this:
void main() async {
final service = Service();
final server = await shelf_io.serve(service.handler, 'localhost', 8080);
print('Server running on localhost:${server.port}');
}
but in web-only project we don't do : final server = await shelf_io.serve(service.handler, 'localhost', 8080);
I was thinking of creating single page application using a shelf router, I saw from the documentation it says that it is compatible with the dart web js platform
My expectation was :
if I write this in web :
router.get('/say-hi/<name>', (Request request, String name) {
return Response.ok('hi $name');
});
then when I will hit /say-hi/ram, then it should have returned "hi ram" in the browser
Related
I call the constructor of OAuth2Strategy in app.controller.ts, i send it the 2 params it needs: options with clientID, callbackURL etc, and a verify callback function. But i have this error, looks like i don't send a verify callback function to the constructor, but i did. The error happens in node_modules/passport-oauth2/lib/strategy.js.
app.controller.ts:
import { Body, Controller, Get, Post, Query, Res, Req, Next, UnauthorizedException, UseGuards } from '#nestjs/common';
import { PartieService, JoueurService, CanalService } from './app.service';
import { Joueur, Partie, Canal } from './app.entity';
import { AuthGuard } from '#nestjs/passport';
import passport = require("passport");
import OAuth2Strategy = require("passport-oauth2");
//var OAuth2Strategy = require('passport-oauth2').OAuth2Strategy;
//import OAuth2Strategy from 'passport-oauth2';
#Controller()
export class AppController {
constructor(private readonly partieService: PartieService, private readonly joueurService: JoueurService,
private readonly canalService: CanalService) {}
#Get('/oauth2')
async oauth2(#Req() req, #Res() res, #Next() next) {
passport.use('oauth2', new OAuth2Strategy(
{
clientID: 'my_clientID',
clientSecret: 'my_clientSecret',
authorizationURL: 'https://api.abc.com/oauth/authorize',
tokenURL: 'https://api.abc.fr/oauth/token',
callbackURL: 'http://localhost:3000/Connection'
},
async (accessToken: string, refreshToken: string, profile: any, done: Function) => {
//console.log(profile);
try {
if (!accessToken || !refreshToken || !profile) {
return done(new UnauthorizedException(), false);
}
const user: Joueur = await this.joueurService.findOrCreate(profile);
return done(null, user);
} catch (err) {
return done(new UnauthorizedException(), false);
}
} ));
passport.authenticate('oauth2');
return res.sendFile("/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/public/connection.html");
}
#Get('/Connection')
//#UseGuards(AuthGuard('oauth2'))
async Callback(#Req() req, #Res() res, #Next() next) {
passport.authenticate('oauth2', (err, user, info) => {
if (err || !user) {
req.session.destroy();
return res.status(401).json({
message: 'Unauthorized',
});
}
req.user = user;
return next();
})(req, res, next);
const utilisateur: Joueur = req.user;
console.log(utilisateur);
}
[...]
}
node_modules/passport-oauth2/lib/strategy.js:
function OAuth2Strategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = undefined;
}
options = options || {};
if (!verify) { throw new TypeError('OAuth2Strategy requires a verify callback'); }
[...]
}
Error:
[Nest] 6550 - 05/02/2023, 18:34:54 ERROR [ExceptionHandler] OAuth2Strategy requires a verify callback
TypeError: OAuth2Strategy requires a verify callback
at new OAuth2Strategy (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/passport-oauth2/lib/strategy.js:84:24)
at Injector.instantiateClass (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/injector.js:340:19)
at callback (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/injector.js:53:45)
at Injector.resolveConstructorParams (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/injector.js:132:24)
at Injector.loadInstance (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/injector.js:57:13)
at Injector.loadProvider (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/injector.js:84:9)
at async Promise.all (index 3)
at InstanceLoader.createInstancesOfProviders (/home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/instance-loader.js:47:9)
at /home/user42/Documents/Projets/ft_transcendence/services/pong/pong/node_modules/#nestjs/core/injector/instance-loader.js:32:13
at async Promise.all (index 1)
`
I tried to change the import OAuth2Strategy many times (like the commented lines). I tried a lot of things but i cannot remember all. I found no answer in internet, and no more with the not-so-well-chatgpt.
I am new in nestjs and this error is weird for me, how can it ask me a parameter that i send ? Can someone help me to resolve this pls ? :)
Sorry if the answer is obvious :/ , it's my first API with nestjs
The error was coming from another file, my bad, it's fixed.
I have a Dart application running on the server side. It is listening at a specific port and working fine. The problem is: my listener is responding to the GET of the favorite icon (favicon).
How can I avoid that?
EDIT: give some code example.
import 'dart:io';
void main() {
print("Starting server.");
HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 4041)
.then(listenForRequests)
.catchError((e) => print (e.toString()));
}
listenForRequests(HttpServer _server) {
_server.listen((HttpRequest request) {
if (request.method == 'GET') {
handleGet(request);
} else {
request.response.statusCode = HttpStatus.METHOD_NOT_ALLOWED;
request.response.write("Unsupported request: ${request.method}.");
request.response.close();
}
},
onDone: () => print('No more requests.'),
onError: (e) => print(e.toString()) );
}
void handleGet(HttpRequest request) {
int requestNumber = 1;
print(requestNumber); // This shows me the request number. Just for information.
print(request.uri); // This shows me the request from the client browser.
request.response.statusCode = HttpStatus.OK;
request.response.close();
}
This is the output of this code:
1
/SOME_REQUEST_FROM_THE_BROWSER
2
/favicon.ico
You can check the requested resource and generate proper response for requests to 'favicon.ico' like
void handleGet(HttpRequest request) {
int requestNumber = 1;
print(requestNumber++); // This shows me the request number.
print(request.uri); // This shows me the request from the client browser.
if(request.requestedUri.path != '/favicon.ico') {
request.response.statusCode = HttpStatus.NOT_FOUND;
} else {
request.response.statusCode = HttpStatus.OK;
}
request.response.close();
}
Can somebody explain what is wrong with the following?
void main() {
var intercept = new HttpInterceptor();
intercept.response = (HttpResponse response) => print('we have a response');
Injector injector = ngBootstrap(module: new MyModule());
var interceptors = injector.get(HttpInterceptors);
interceptors.add(intercept);
}
Thanks in advance
EDIT:
And here is how I do an http request (from inside a directive):
#NgDirective(
selector: '.my-selector')
class MyDirective implements NgAttachAware {
#NgOneWay('id')
String id;
Element self;
MyDirective(Element el) {
self = el;
}
void attach() {
final String _urlBase = 'http://www.some-site.com/';
HttpRequest req = new HttpRequest();
req.open('GET', _urlBase + id);
req.overrideMimeType('text\/plain; charset=x-user-defined');
req.onLoadEnd.listen((e) {
if (req.status == 200) {
// do something useful
} else {
print('download failed');
}
});
req.send();
}
}
Requests return successfully but the interceptor never fires. Why?
You must use the AngularDart built-in service "Http" and not the dart:html HttpRequest class.
The HttpInterceptors only work on when using that service which wraps the HttpRequest class.
In other words, inject Http in the directive´s constructor:
MyDirective(Element el, Http http) {
self = el;
this._http = http;
}
I have a SignalR client in a Windows Service that successfully calls a Server method in an MVC app. First the Server Code:
public class AlphaHub : Hub
{
public void Hello(string message)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
Clients.All.addNewMessageToPage(message);
// Send message to Windows Service
}
and
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.MapSignalR("/signalr", new HubConfiguration());
}
}
The Windows Service client is:
protected override async void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
try
{
var hubConnection = new HubConnection("http://localhost.com/signalr", useDefaultUrl: false);
IHubProxy alphaProxy = hubConnection.CreateHubProxy("AlphaHub");
await hubConnection.Start();
await alphaProxy.Invoke("Hello", "Message from Service");
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
It sends a message to the MVC Server. Now I want to call the other way from server to client. The Client Programming Guide has the following code examples which will NOT work as this is not a desktop.
WinRT Client code for method called from server without parameters (see WPF and Silverlight examples later in this topic)
var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHub.On("notify", () =>
// Context is a reference to SynchronizationContext.Current
Context.Post(delegate
{
textBox.Text += "Notified!\n";
}, null)
);
await hubConnection.Start();
How can I call a method on the client?
The .NET client side code seems fine. You can simply get rid of Context.Post since your client is running inside of a Windows Service and doesn't need a SyncContext:
protected override async void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
try
{
var hubConnection = new HubConnection("http://localhost.com/signalr", useDefaultUrl: false);
IHubProxy alphaProxy = hubConnection.CreateHubProxy("AlphaHub");
stockTickerHub.On("Notify", () => eventLog1.WriteEntry("Notified!"));
await hubConnection.Start();
await alphaProxy.Invoke("Hello", "Message from Service");
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
You can invoke the "Notify" callback from inside your AlphaHub on the server like so:
public class AlphaHub : Hub
{
public void Hello(string message)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
Clients.All.addNewMessageToPage(message);
// Send message to the Windows Service
Clients.All.Notify();
}
Any client will be able to listen to these notifications since we are using Clients.All. If you want to avoid this, you need some way to authenticate your Windows Service and get its ConnectionId. Once you have that, you can send to the Windows Service specifically like so:
Clients.Client(serviceConnectionId).Notify();
Hope this helps.
Windows Service with self hosted SignalR
public partial class MyWindowsService : ServiceBase
{
IDisposable SignalR { get; set; }
public class SignalRStartup
{
public static IAppBuilder App = null;
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration()
{
// EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
}
}
public MyWindowsService()
{
InitializeComponent();
}
protected override void OnStart(string[] args) { Start(); }
protected override void OnStop() { Stop(); }
public void Start()
{
SignalR = WebApp.Start<SignalRStartup>("http://localhost:8085/signalr");
CallToMvcJavascript();
}
public new void Stop()
{
SignalR.Dispose();
}
private void CallToMvcJavascript(){
GlobalHost.ConnectionManager.GetHubContext<MyHub>().Clients.All.addNotice(// object/data to send//);
}
}
The Hub in the Windows Service
public class MyHub : Hub
{
public void Send()
{
Clients.All.confirmSend("The service received the client message");
}
}
The Javascript
$.connection.hub.logging = true;
$.connection.hub.url = "http://localhost:8085/signalr";
var notices = $.connection.myHub;
notices.client.addNotice = function(notice) {
console.log(notice);
};
notices.client.confirmSend = function(msg) {
alert(msg);
};
$.connection.hub.start().done(function() {
$('#myTestBtn').on('click', function() {
notices.server.send();
});
});
I’m trying to log out Web API Request Content – i.e. the json string. I implemented an ITraceWriter class (example) and configured it so that Web API calls it in the pipeline. But if I read the request.Content or copy into to a stream to read it is not available for the method resulting in a null model. This post talks about that issue a little. Anyone have experience logging out inbound Web API request content and know what the best approach is?
Thanks
Update A
I created a simple sample Web API project to rule out anything in my project and I still see that the model will be null because of logging. I simply test a few times in a row by posting via Fidder and see my model comes in null. With breakpoints in place, it might work which is why I think there is a sync/timing issue. Any thoughts on how to get this to work?
Header:
User-Agent: Fiddler
Host: localhost:56824
Content-Type: application/json
Content-Length: 22
Body:
{
"A":1,"B":"test"
}
Here's the code:
Controller:
public class ValuesController : ApiController
{
[HttpPost]
public void Post(ValuesModel model)
{
if (model == null)
{
Debug.WriteLine("model was null!");
}
else
{
Debug.WriteLine("model was NOT null!");
}
}
}
Model:
public class ValuesModel
{
public int A { get; set; }
public string B { get; set; }
}
Logger:
public class APITraceLogger : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Content != null)
{
// This can cause model to be null
request.Content.ReadAsStringAsync().ContinueWith(s =>
{
string requestText = s.Result;
Debug.WriteLine(requestText);
});
// and so can this
//request.Content.ReadAsByteArrayAsync()
// .ContinueWith((task) =>
// {
// string requestText = System.Text.UTF8Encoding.UTF8.GetString(task.Result);
// Debug.WriteLine(requestText);
// });
}
// Execute the request, this does not block
var response = base.SendAsync(request, cancellationToken);
// TODO:
// Once the response is processed asynchronously, log the response data
// to the database
return response;
}
}
Wiring up logger in WebApiConfig class:
config.MessageHandlers.Add(new APITraceLogger());
Update B
It seems like it is now working if I change the logger to the following code adding the await, async and returning the result. Seems like something I'm not understanding in the async code or truly a timing issue or something.
public class APITraceLogger : DelegatingHandler
{
protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Content != null)
{
// This does seem to work - is it because it is synchronous? Is this a potential problem?
var requestText = await request.Content.ReadAsStringAsync();
Debug.WriteLine(requestText);
}
// Execute the request, this does not block
var response = base.SendAsync(request, cancellationToken);
// TODO:
// Once the response is processed asynchronously, log the response data
// to the database
return response.Result;
}
}
As Filip mentions in that post ReadAsStringAsync or ReadAsByteArrayAsync methods buffer the request content internally. This means that even if your incoming request's stream type is a non-buffered stream, you could safely do a ReadAsStringAsync/ReadAsByteArrayAsync at a message handler for example, and also expect the model binding to work fine.
By default, a request's stream is buffered in both webhost and selfhost cases. But if you would like to check if using ReadAsStringAsync/ReadAsByteArrayAsync and model biding works fine even in non-buffered mode, you can do the following to force non-buffered mode:
public class CustomBufferPolicySelector : WebHostBufferPolicySelector
{
public override bool UseBufferedInputStream(object hostContext)
{
//NOTE: by default, the request stream is always in buffered mode.
//return base.UseBufferedInputStream(hostContext);
return false;
}
}
config.Services.Replace(typeof(IHostBufferPolicySelector), new CustomBufferPolicySelector());
Just FYI...the above policy selector works only for Web Host currently. If you would like to do a similar test in SelfHost, then do the following:
//NOTE: by default, the transfer mode is TransferMode.Buffered
config.TransferMode = System.ServiceModel.TransferMode.StreamedRequest;
After Update B of the post above:
You could modify your handler like below:
public class LoggingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Content != null)
{
string requestContent = await request.Content.ReadAsStringAsync();
}
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
if (response.Content != null)
{
string responseContent = await response.Content.ReadAsStringAsync();
}
return response;
}
}