So I upgraded my IDE and SDK and now the following code doesn't work anymore. I am adding some text here to try to get around this sites fascist validation on posts it's pretty aggressive.
String URL = "http://www.google.com";
Future future = client.getUrl(Uri.parse(URL))
.then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) {
print('Status code: ${response.statusCode}');
print('Headers\n${response.headers}');
});
});
I am getting the following exception now.
Uncaught Error: Bad state: No elements
Stack Trace:
Any ideas?
Works for me using Dart 0.6.3.3_r24898 on Windows.
Are you sure this is all the code you have? In the stack trace I see WebSocketImpl, are you using WebSockets?
Related
i'm trying to do a post request but all the time i get this error
Uncaught Error: XMLHttpRequest error.
i' working on dartpad on line and i'm using the package http.dart .I don't get the problem despite i post a json format i dont understand why the error is with the xml ?!
this my code :
import 'package:http/http.dart' as http;
void main() async {
// This will be sent as form data in the post requst
var map = new Map<String, dynamic>();
map['username'] = '**********';
map['password'] = '**********';
final response = await http.post(
Uri.parse('************'),
body: map,
);
print(response.body);
}
I suggest the following:
Verify that your URI is correct, I tried your code on DartPad with a simple GET request onto a Free API I found on the web and I get no errors
Verify that your endpoint has no weird CORS errors with another client (e.g. postman or Dio, see below)
Verify that you don't have weird cache values onto your machine. Doing a flutter clean && flutter pub get might help
Consider using Dio (pub.dev) as your http client as the dart's inner http package isn't quite ready for production imho.
I am using the http package to call my API, but every request takes 8+ seconds to complete.
I have tried calling the same route via browser and postman and I get the response in less than a second. Also, I can assure that there is no issue with my internet connection.
class ApiRest {
Future<List<Product>> getProducts() async {
final apiResponse = await http.get(Uri.parse('some route'));
final resBody = jsonDecode(apiResponse.body);
return resBody['products']
.map<Product>((product) => Product.fromJson(product))
.toList();
}
}
Additionally, I tried applying the approach recommended by this answer, using the HTTP Client(), which didn't make a difference either.
Is there anything I am doing wrong or inefficient?
Lastly, the latest version of the http package for Flutter is currently 0.13.4. Do you think that the issue might be with this package? Or it might not be stable enough?
I'm developing an Angular2 application. It seems when my access-token expires the 401 HTTP Status code gets changed to a value of 0 in the Response object. I'm receiving 401 Unauthorized yet the ERROR Response object has a status of 0. This is preventing me from trapping a 401 error and attempting to refresh the token. What's causing the 401 HTTP status code to be changed into HTTP status code of 0?
Here's screenshot from Firefox's console:
Here's my code:
get(url: string, options?: RequestOptionsArgs): Observable<any>
{
//console.log('GET REQUEST...', url);
return super.get(url, options)
.catch((err: Response): any =>
{
console.log('************* ERROR Response', err);
if (err.status === 400 || err.status === 422)
{
return Observable.throw(err);
}
//NOT AUTHENTICATED
else if (err.status === 401)
{
this.authConfig.DeleteToken();
return Observable.throw(err);
}
else
{
// this.errorService.notifyError(err);
// return Observable.empty();
return Observable.throw(err);
}
})
// .retryWhen(error => error.delay(500))
// .timeout(2000, new Error('delay exceeded'))
.finally(() =>
{
//console.log('After the request...');
});
}
This code resides in a custom http service that extends Angular2's HTTP so I can intercept errors in a single location.
In Google Chrome, I get this error message:
XMLHttpRequest cannot load https://api.cloudcms.com/repositories/XXXXXXXXXXXXXXXX/branches/XXXXXXXXXXXXXXXX/nodesXXXXXXXXXXXXXXXX. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://screwtopmedia.local.solutiaconsulting.com' is therefore not allowed access. The response had HTTP status code 401.
This is confusing because I am including 'Access-Control-Allow-Origin' header in request.
Here's a picture of results received in Google Chrome:
I've tried accessing 'WWW-Authenticate' Response Header as a means to trap for 401. However, the following code returns a NULL:
err.headers.get("WWW-Authenticate")
It's puzzling that I'm getting a CORS issue because I'm not getting any CORS errors when a valid access token is provided.
How do I trap for 401 HTTP status code? Why is 401 HTTP status code being changed to 0?
Thanks for your help.
The issue is related to CORS requests, see this github issue
No 'Access-Control-Allow-Origin' header is present on the requested
resource
means that 'Access-Control-Allow-Origin' is required in the response headers.
Angular is not getting any status codes, that's why it gives you a 0 which is caused by browser not allowing the xml parser to parse the response due to invalid headers.
You need to append correct CORS headers to your error response as well as success.
If cloudcms.com do to not set the Access-Control-Allow-Origin in 401 response, then nothing much you can do. You properly have to open support ticket with them to confirm if that is normal behavior.
javascript in browsers(FF, Chrome & Safari) I tested won't receive any info if CORS error occur, other than status 0. Angular2 has no control of it.
I created a simple test and get the same result as yours:
geturl() {
console.log('geturl() clicked');
let headers = new Headers({ 'Content-Type': 'application/xhtml+xml' });
let options = new RequestOptions({ 'headers': headers });
this.http.get(this.url)
.catch((error): any => {
console.log('************* ERROR Response', error);
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Web Server error';
return Observable.throw(error);
})
.subscribe(
(i: Response) => { console.log(i); },
(e: any) => { console.log(e); }
);
}
After much googling, I found the following(https://github.com/angular/angular.js/issues/3336):
lucassp commented on Aug 19, 2013
I found the issue for a while now but I forgot post here a reply. EVERY response, even Error 500, must have the CORS headers attached. If the server doesn't attach the CORS headers to the Error 500 response then the XHR Object won't parse it, thus the XHR Object won't have any response body, status, or any other response data inside.
Result from Firefox network monitor seems supporting the above reason.
Javascript request will receive empty response.
Plain url request(copy&paste the link in the address bar) will get response body
Javascript use XHRHttpRequest for http communication.
When a XHR reply arrive, the browser will process the header, that's why you will see those 401 network messages. However, if the XHR reply is from a different host then the javascript AND the response header contain no CORS header(eg Access-Control-Allow-Origin: *), the browser will not pass any info back to the XHR layer. As a result, the reply body will be completely empty with no status(0).
I tested with FF 48.0.1, Chrome 52.0.2743.116 and Safari 9.1.2, and they all have the same behavior.
Use browser network monitor to check response header for those 401 Unauthorized entries, it is very likely that there is no Access-Control-Allow-Origin header and causing the issue you are facing. This can be a bug or by design on the service provider side.
Access-Control-Allow-Origin is a response only http header. For more information of https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_response_headers
I work for Cloud CMS. I can confirm that we properly set CORS headers on API calls. However, for 401 responses the headers are not getting set properly. This has been resolved and the fix will be available on the public API at the end of this week.
BTW if you use our javascript driver https://github.com/gitana/gitana-javascript-driver instead of writing to the API directly then the re-auth flow is handled automatically and you do not need to trap 401 errors at all.
Stumbled upon this item:
What happens in my case was that:
I was requesting REST from different domain
The resource returned 401, but there was no "Access-Control-Allow-Origin" set in the error response.
Chrome (or your browser) received 401 and showed in network tab (See below count : 401), but never passed to Angular
since there was no CORS allowed (missing "Access-Control-Allow-Origin" header) - Chrome could not pass this response into Angular. This way I could see 401 in the Chrome but not in Angular.
Solution was simple (extends on TimothyBrake's answer) - to add the missing header into the error response. In Spring boot I put: response.addHeader("Access-Control-Allow-Origin", "*"); and I was sorted out.
#Component
public class JwtUnauthorizedResponseAuthenticationEntryPoint
implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"You would need to provide the Jwt Token to Access This resource");
}
}
PS: Make sure the bean is provided into HttpSecurity config in your WebSecurityConfigurerAdapter. Refer to: https://www.baeldung.com/spring-security-basic-authentication if in doubt.
Hope this helps.
According to W3C, if the status attribute is set to 0, it means that:
The state is UNSENT or OPENED.
or
The error flag is set.
I think that this isn't an Angular2 issue, it seems like your request has a problem.
I had the same issue and was due to the server not sending the correct response (even though the console log stated a 401 the Angular error had status 0). My server was Tomcat with Java application using Spring MVC and Spring Security.
It is now working using folowing setup:
SecurityConfig.java
...
protected void configure(HttpSecurity http) throws Exception {
....
http.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
// allow CORS option calls
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
...
SomeAuthenticationEntryPoint.java
#Component
public class SomeAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
HttpStatus responseStatus = HttpStatus.UNAUTHORIZED;
response.sendError(responseStatus.value(), responseStatus.getReasonPhrase());
}
}
web.xml
<error-page>
<error-code>403</error-code>
<location>/errors/unauthorised</location>
</error-page>
<error-page>
<error-code>401</error-code>
<location>/errors/unauthorised</location>
</error-page>
Controller to handle the /errors/... previously defined
#RestController
#RequestMapping("/errors")
public class SecurityExceptionController {
#RequestMapping("forbidden")
public void resourceNotFound() throws Exception {
// Intentionally empty
}
#RequestMapping("unauthorised")
public void unAuthorised() throws Exception {
// Intentionally empty
}
}
}
You should use a 3rd party http protocol monitor (like CharlesProxy) rather than Chrome dev tools to confirm which headers are actually being sent to the API service and if it is returning a 401.
I have a single GWT web-application integrated with Spring MVC. I have a working Controller which works perfectly and is unit tested to accept POSTed JSON data and returns JSON data.
From within the same application, to avoid any SOP cross-site domain issues, I am making a call with a RequestBuilder to POST the same json data, and I expect JSON data back.
I created a basic java class that should make a call, but I have a few issues. This running web-app is running in hosted mode in Jetty in Eclipse. I have done a ton of research on how GWT should make a call to an existing web-service with a simple HTP request.
The first issue from my unit test is that:
String baseUrl = GWT.getModuleBaseURL();
is not working and I get:
java.lang.UnsatisfiedLinkError: com.google.gwt.core.client.impl.Impl.getModuleBaseURL()Ljava/lang/String;
I think I know what the correct URL should be, so when I hard-code the url correctly, and execute this code:
String url = getRootUrl() + "rest/pendingInvoices/searchAndCount";
System.out.println("PendingInvoiceDataSource: getData: url=" + url);
// Send request to server and catch any errors.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
builder.setHeader("Accept", "application/json");
builder.setHeader("Content-type", "application/json");
// builder.setRequestData(requestData);
try
{
System.out.println("PendingInvoiceDataSource: SEND REQUEST: getData: requestData=" + requestData);
Request request = builder.sendRequest(requestData, new RequestCallback()
{
public void onError(Request request, Throwable exception)
{
System.out.println("Couldn't retrieve JSON");
}
#Override
public void onResponseReceived(Request request, Response response)
{
if (200 == response.getStatusCode())
{
// updateTable(JsonUtils.safeEval(response.getText()));
System.out.println("data=" + response.getText());
}
else
{
System.out.println("Couldn't retrieve JSON (" + response.getStatusText() + ")");
}
}
});
}
catch (RequestException e)
{
System.out.println("Couldn't retrieve JSON");
}
I get this error on he sendRequest:
java.lang.UnsatisfiedLinkError: com.google.gwt.xhr.client.XMLHttpRequest.create()Lcom/google/gwt/xhr/client/XMLHttpRequest;
at com.google.gwt.xhr.client.XMLHttpRequest.create(Native Method)
at com.google.gwt.http.client.RequestBuilder.doSend(RequestBuilder.java:383)
at com.google.gwt.http.client.RequestBuilder.sendRequest(RequestBuilder.java:261)
I think this might be a quick fix, or maybe something small I have forgotten, so I'll try some more testing and see what I can find.
Everything client in GWT is only meant to run on the client-side: compiled to JS or in DevMode.
Only shared, server and vm classes can be used on the server-side.
If you want to get your server URL, use the appropriate methods from the HttpServletRequest (or whatever it is in Spring MVC as it seems from how you tagged the question that's what you're using).
If you want to make HTTP requests from your server, use an HttpURLConnection, or OkHttp, Apache Http Components or similar libraries, or even Spring's own HTTP client API.
Actually, it was only the Unit Test that was having a problem. Once I actually tried to run the deployed code, it all worked. I'll still try h GWTTestCase as suggested in order to get the unit test working.
But everything worked correctly when I ran the deployed code.
I also changed: String baseUrl = GWT.getModuleBaseURL();
which gave me:
http://localhost:8888/MyProject
To: String baseUrl = GWT.getHostPageBaseURL();
which gave me:
http://localhost:8888/
and that all worked.
I'm making an internet application with GWT, and one of the features that I've been stuck on for a few weeks is getting the users contact data from google data. I've tried things like GWT-GData and they don't seem to play nicely with the current version of GWT, so I tried going the more traditional approach with OAuth and doing an HTTP Get request. I haven't been receiving anything back as a response, and couldn't figure out why, and I happened across my javascript error log and I'm getting:
"Origin [site name here] is not allowed by Access-Control-Allow-Origin"
I've done some reading and I have a decent idea of what's going on, but I don't know how to get around it in GWT. I've found plenty of read-ups on how to get around it with other platforms, but I haven't seen anything for GWT. Can anyone offer any wisdom?
Edit:
Here is the code I'm using:
public static void doGet(String url, String oauthToken) {
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
Request request = builder.sendRequest(oauthToken, new RequestCallback() {
#Override
public void onError(Request request, Throwable e) {
GWT.log(e.toString(), e);
}
#Override
public void onResponseReceived(Request request, Response response) {
Window.alert("HEADER:" + response.getHeadersAsString()
+ "\nSTATUS: " + response.getStatusText()
+ "\nTEXT: " + response.getText());
}
});
} catch (RequestException e) {
GWT.log(e.toString(), e);
}
}
There's nothing you can do but configure the server to accept the origin of the request (i.e. add it to the returned Access-Control-Allow-Origin.
Because it's GData, it might however simply be a mistake on your side re. the requested URL: there's no Access-Control-Allow-Origin when you request data in Atom format, only when requesting JSON (and the value is then * which allows everyone, so shouldn't cause any issue like you're seeing): http://code.google.com/p/chromium/issues/detail?id=45980#c2
While this doesn't answer the original question, the following may help others who have the same underlying issue that arrived at this page (I'm using a GWT client with a Groovy web server). This did the trick on the server:
HttpExchange.getResponseHeaders().add("Access-Control-Allow-Origin","*");