Dart Restful Server doesnt show response data - dart

I was not 100% sure on how to create a Restful Dart API I can make calls to, but i wanted to try. I wrote the following code:
import "package:rpc/rpc.dart";
import "dart:io";
final ApiServer _apiServer = new ApiServer(prettyPrint:true);
main() async{
_apiServer.addApi(new TestServer());
HttpServer server = await HttpServer.bind(InternetAddress.ANY_IP_V4, 8088);
server.listen(_apiServer.httpRequestHandler);
print('Server listening on http://${server.address.host}:'
'${server.port}');
}
#ApiClass(name:'test_server', version: 'v1', description: 'This is a test server api to ping for some quick sample data.')
class TestServer {
#ApiMethod(method:'GET', path: 'users')
List<User> getUsers(){
List<User> users = new List<User>();
return users;
}
#ApiMethod(method: 'GET', path: 'users/{id}')
User getUser(int id){
User u;
///TODO: Guts of User.
u = new User(id, "f_test_$id", "f_test_$id");
return u;
}
#ApiMethod(method:'POST', path: 'users/user/{id}/add')
User postUser(int id, UserData usr){
User u;
///TODO: Post the user.
u = User.fromUsrData(usr);
return u;
}
}
It is a pretty simple, small one which isnt actually doing anything.
When I run the dart file it will say something like:
Observatory listening on http://127.0.0.1:64969
Server listening on http://0.0.0.0:8088
So it makes me believe that i should be able to ping the server in localhost. I make a call in my browser to http://localhost:8088/test_server/v1/users
and it says: {"error":{"code":400,"message":"Invalid request, missing API name and/or version: http://localhost:8088/."}} which confuses me.
Did i do something wrong somewhere in my definition or how to access the localhost API?
EDIT It seems that when I go to that URL, it sits in a perpetual state of pending. It doesnt do do anything other than that.

After a deeper understanding of the issue, changing the name around etc, It seems that my server was having some issues so i needed to end the Dart execution, and restart the server.
When trying to go to the link again: http://localhost:8088/test/v1/users
it worked exactly as it should.

Related

how to run geb functional test in https?

My application requires the app to run in https since the browser sends payment data to payment gateway through javascript library.
If the app is run in http then this error is thrown by the payment gateway.
I have created a simple hello world app and wrote a simple geb spec.
I dont seem to find a way to run the server in https mode. I dont find any helpful resource in the web as well.
Right now it is running in http mode in random port
Grails application running at http://localhost:54461 in environment: test
I have tried adding https port in build.gradle as
integrationTest {
systemProperty "webdriver.chrome.driver", "C:\\webdrivers\\chromedriver.exe"
jvmArgs(
'-Dgrails.server.port.https=8443'
)
}
But that seems to get ignored.
I have also tried setting the https port in intellij run configuration as shown below.
I have published the app code in github for reference.
https://github.com/learningcscience/gebhttps
I appreciate any help. Thanks!
UPDATE:
Today i think i made a little more progress.
I could now run the app in a fixed port. I ran the app in 8443 which is for https.
I did this using the spring boot test annotation
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
In the console now it shows
Grails application running at http://localhost:8443 in environment: test
Starting ChromeDriver 100.0.4896.20 (f9d71f93d32a6487809d6f35a9670c879fe97dfe-refs/branch-heads/4896#{#203}) on port 31898
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
https://docs.grails.org/latest/guide/testing.html
Now i just need to make the app run using the https rather than http.
I have updated the code in github repo.
https://github.com/learningcscience/gebhttps
I appreciate any help! Thanks!
ok. The problem is finally solved.
The last help came from the grails community at https://grails.slack.com/
Thanks Mattias Reichel for the help.
I am now going to put step by step process so that others might not get stuck with this issue.
In order to run functional geb test in https you first need to put SpringBootTest annotation as mentioned in above UPDATE: section.
I am pasting here again
#Integration
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class EventCreationSpec extends GebSpec {
After that you set baseurl in src/integration-test/resources/GebConfig.groovy.
I put baseUrl = "https://localhost:8443/"
My GebConfig looks like this
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.firefox.FirefoxDriver
environments {
// run via “./gradlew -Dgeb.env=chrome iT”
chrome {
driver = {
System.setProperty('webdriver.chrome.driver', 'C:\\webdrivers\\chromedriver.exe')
new ChromeDriver()
}
}
// run via “./gradlew -Dgeb.env=chromeHeadless iT”
chromeHeadless {
driver = {
ChromeOptions o = new ChromeOptions()
o.addArguments('headless')
new ChromeDriver(o)
}
}
// run via “./gradlew -Dgeb.env=firefox iT”
firefox {
driver = { new FirefoxDriver() }
}
}
baseUrl = "https://localhost:8443/"
After that you need to create a application-test.yml file in src/integration-test/resources/
The application-test.yml file looks like this
server:
port: 8443
ssl:
enabled: true
keyStore: c:/Users/user/selfsigned.jks
keyStorePassword: pepsicola
keyAlias: tomcat
you need to create self signed certificate.
You can go through this process to create the certificate
https://grails.org/blog/2017-06-28.html
In the configuration above
my certificate was in selfsigned.jks keystore in the path c:/Users/user/selfsigned.jks
After that the functional test will fire in https mode
In my case
http://localhost:8443/roadrace
here is what the gebspec should look like
Note the SpringBootTest annotation at the top.
#Integration
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
#Stepwise
class EventCreationSpec extends GebSpec {
def grailsApplication
def springSecurityService
def timeService
def setup() {
}
def cleanup() {
}
void "Create and publish event"() {
when:"The home page is visited"
go '/roadrace/'
$("#details-button").click()
$("#proceed-link").click()
... rest of gebspock test steps....
then:"The title is correct"
title == "Homepage"
}
}
Please note that i had to go to /roadrace/ because the roadrace is the app context path.
If you dont have context path you can go to go '/'
The final hurdle can be when the browser fires up in https it might show
For this using geb you can click on the Advanced and then Proceed to localhost (unsafe) links
I just click the links like this
go '/roadrace/'
$("#details-button").click()
$("#proceed-link").click()
That's all! Now the geb functional test runs in https. Since it is https you can also now communicate to test payment gateway.

How do I get my physical device running React Native on Expo Go to communicate with my app's rails backend api?

I am currently trying to run my react-native/rails app on my phone for testing purposes. I can run my sign in and log in screens fine because they do not communicate with my server until the user info is entered. When running my server i use:
$ rails s --binding=0.0.0.0
I do not receive any errors other than knowing my server is not being communicated with. This all works fine on my Android Studio Emulator as well.
// one of my fetch GET requests
export function requestCurrentUser(username, auth_token) {
return function action(dispatch) {
const request = fetch(`'http://10.0.2.2:3000'/users/${username}`, {
method: 'GET',
headers: {
"Authorization": auth_token
}
});
return request.then(
response => response.json(),
err => console.log("user error"),
)
.then(
json => dispatch(receiveCurrentUser({id: json.id, email: json.email, username: json.username})),
err => console.log("user json error"),
);
}
}
I've tried changing my Phone IP settings to a 10.0.2.2 Gateway, and using my phone's IP in my fetch request. I feel like I am missing something conceptually. Thanks in advance.
In fetch request you need to use the IP from the machine that are running the rails server,
probably your notebook and use the same network to connect your app and your rails backend api. In order to test, you can try directly access your api in your phone browser accessing http://IP_FROM_RAILS_MACHINE:3000

NestJS microservices error with "No matching message handler"

I'm building an application with microservices communicating through RabbitMQ (request-response pattern). Everything works fine but still I have a problem with error "There is no matching message handler defined in the remote service." - When I send POST to my Client app, it should simply send the message with data through client (ClientProxy) and the Consumer app should response. This functionality actually works, but always only for the second time. I know it sounds strange but on my first POST request there is always the error from Client and my every second POST request works. However this problem is everywhere in my whole application, so the particular POST request is just for the example.
Here is the code:
Client:
#Post('devices')
async pushDevices(
#Body(new ParseArrayPipe({ items: DeviceDto }))
devices: DeviceDto[]
) {
this.logger.log('Devices received');
return this.client.send(NEW_DEVICES_RECEIVED, devices)
}
Consumer:
#MessagePattern(NEW_DEVICES_RECEIVED)
async pushDevices(#Payload() devices: any, #Ctx() context: RmqContext) {
console.log('RECEIVED DEVICES');
console.log(devices);
const channel = context.getChannelRef();
const originalMsg = context.getMessage();
channel.ack(originalMsg);
return 'ANSWER';
}
Client has the RMQ settings with queueOptions: {durable: true} and the consumer as well queueOptions: {durable: true} with noAck: false
Please do you have any ideas what may causes the problem? I have tried sending the data with JSON.stringify and changing the message structure to {data: devices} but the error is still there.
I had same error and finally solve it today.
In my project, there is an api-gateway as a hybrid application to receive requests and pass data to other systems, every second request gives an error like below.
error: There is no matching message handler defined in the remote service.
Then I tried to remove the api-gateway hybrid application scope in the code below, the error is gone, hope this helps you out with this.
// api-gateway main.ts
const app = await NestFactory.create(AppModule);
// run as a hybrid app —→ remove it
app.connectMicroservice({
transport: Transport.RMQ,
noACK: false,
options: {
urls: [`amqp://${rmqUser}:${rmqPassword}#127.0.0.1:5672`],
queue: 'main_queue',
queueOptions: {
durable: false,
},
},
});
// run hybrid app
await app.startAllMicroservices(); —→ remove it
await app.listen(3000);
I solved this issue by placing the #EventPattern decorator on to a #Controller decorator method
I had this error while NOT using RabbitMQ. I found very little help online around this error message outside of it being related to RabbitMQ.
For me it was an issue where I was importing a DTO from another microservice in my microservice's Controller. I had a new DTO in my microservice that has a similar name to one in another microservice. I accidentally selected the wrong one from the automated list.
Since there wasn't any real indicator that my build was bad, just this error, I wanted to share in case others made the same mistake I did.
I encountered this same issue today and could not find any solution online and stumbled upon your question. I solved it in a hacky way and am not sure how it will behave when the application scales.
I basically added one #EventPattern (#MessagePattern in your case) in the controller of the producer microservice itself. And I called the client.emit() function twice.
So essentially the first time it gets consumed by the function that is in the producer itself and the second emit actually goes to the actual consumer.
This way only one POST call is sufficient.
Producer Controller:
#EventPattern('video-uploaded')
async test() {
return 1;
}
Producer client :
async publishEvent(data: VideosDto) {
this.client.emit('video-uploaded', data);
this.client.emit('video-uploaded', data);
}
I've experienced the same error in my another project and after some research I've found out that problem is in the way of distributing messages in RabbitMQ - named round-robin. In my first project I've solved the issue by creating a second queue, in my second project I'm using the package #golevelup/nestjs-rabbitmq instead of default NestJS library, as it is much more configurable. I recommend reading this question

Azure AD Ms Identity callback URL (error AADSTS50011)

I'm integrating Azure AD and MS-Identity on a web app with Angular.
It works on my machine, but when I deploy it, I get an issue with the callback URL.
First, to make sure the callback URL is ok, I extract it from the microsoft login popup window's URL:
Then, I url decode the content. The URL seems fine and it is available in my Azure app's redirect URL.
Then I login to Microsoft normally and I get this error (AADSTS50011):
Then I inspect the URL again (inside the query string from the urldecoded popup window's URL) and now the URL seems to have been "tampered with".
It's now something like this:
http://somedomain:80/some_page/somequerystring
instead of
https://somedomain/some_page/somequerystring
so I wonder if it's part of the problem or if it's normal behavior.
It is also mentionned "If you contact your administrator, send this info to them." I suppose I'm the "administrator" so what can I do with that "Copy info to clipboard" info to investigate the problem?
Is your application hosting on http (80) or https (443)? If your app service is terminating your TLS connection and handling that for you instead of your app, your sign-on will construct the redirect using the http request scheme. I hooked into the OnRedirectToIdentityProvider event to correct the scheme.
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
Configuration.Bind("AzureAd", options);
options.Events ??= new OpenIdConnectEvents();
options.Events.OnRedirectToIdentityProvider += _fixRedirect;
});
...
private async Task _fixRedirect(RedirectContext context)
{
context.Request.Scheme = "https";
if(!context.ProtocolMessage.RedirectUri.StartsWith("https"))
context.ProtocolMessage.RedirectUri =
context.ProtocolMessage.RedirectUri.Replace("http", "https");
await Task.CompletedTask;
}

rails responding to cross domain request developing locally, spotify app development

So Im messing around with developing a spotify app, trying to get it to talk to my local rails application API. I cant get anything other than a req.status 0 when I try it.
I think its either a problem with the spotify manifest.json file, not allowing the port:3000 to go on the url you set in required permissions, but it also says the following in their documentation.
https://developer.spotify.com/technologies/apps/tutorial/
If you need to talk to an outside web API you're welcome to, as long as you abide by the rules set in the Integration Guidelines. Please note that when talking with a web API, the requests will come from the origin sp://$APPNAME (so sp://tutorial for our example) - make sure the service you are talking to accepts requests from such an origin.
So, Im not sure if rails is set to not allow this sort of thing, or if its an issue with the putting the port into the required permissions, but my request
var req = new XMLHttpRequest();
req.open("GET", "http://127.0.0.1:3000/api/spotify/track/1.json", true);
console.log(req);
req.onreadystatechange = function() {
console.log(req.status);
console.log(req.readyState);
if (req.readyState == 4) {
if (req.status == 200) {
console.log("Search complete!");
console.log(req.responseText);
}
}
};
req.send();
Always returns status 0 where as their example:
var req = new XMLHttpRequest();
req.open("GET", "http://ws.audioscrobbler.com/2.0/?method=geo.getevents&location=" + city + "&api_key=YOUR_KEY_HERE", true);
req.onreadystatechange = function() {
console.log(req.status);
if (req.readyState == 4) {
console.log(req);
if (req.status == 200) {
console.log("Search complete!");
console.log(req.responseText);
}
}
};
req.send();
Will return a 403 response at least. its like the request is not being made or something?
Anyone have any idea what might be going on?
Much appreciated!
When talking to external services from a Spotify App, even if they're running on your local machine, you need to make sure that two things are in place correctly:
The URL (or at least the host) is in the RequiredPermissions section of your manifest. Port doesn't matter. http://127.0.0.1 should be fine for your case.
The server is allowing the sp://your-app-id origin for requests, as noted in the documentation you pasted in your question. This is done by setting the Access-Control-Allow-Origin header in your service's HTTP response. People often set it to Access-Control-Allow-Origin: * to allow anything to make requests to their service.
Thanks for help, I got it figured out, I think it was multiple things, with one main Im an idiot moment for not trying that earlier
First off, I had to run rails on port 80, as obviously if Im accessing my site from 127.0.0.1:3000, thats not going to work if spotify app is requesting 127.0.0.1 unless I can load that directly in the browser, which you cannot unless you run on 80. That is done via
rvmsudo rails server -p 80
Need to use rvmsudo because changing port requires permissions.
Next I had to set access controll allow origin as noted above, that can be done in rails 3 by adding before filter to your app controller as follows.
class ApplicationController < ActionController::Base
logger.info "I SEE REQUEST"
before_filter :cor
def cor
headers["Access-Control-Allow-Origin"] = "*"
headers["Access-Control-Allow-Methods"] = %w{GET POST PUT DELETE}.join(",")
headers["Access-Control-Allow-Headers"] = %w{Origin Accept Content-Type X-Requested-With X-CSRF-Token}.join(",")
head(:ok) if request.request_method == "OPTIONS"
end
end
Finally, and most importantly (sigh), you cant just righclick and reload your spotify app when you make changes to your manifest file, exit spotify completely and restart it!

Resources