How to create cross-domain request?

2019-01-01 16:41发布

问题:

How to create a cross-domain request using Angular 2?

Can you provide an example?
Like a request between localhost:3000 and localhost:8000 cross-domain

回答1:

In fact, there is nothing to do in Angular2 regarding cross domain requests. CORS is something natively supported by browsers. This link could help you to understand how it works:

  • http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
  • http://restlet.com/blog/2016/09/27/how-to-fix-cors-problems/

To be short, in the case of cross domain request, the browser automatically adds an Origin header in the request. There are two cases:

  • Simple requests. This use case applies if we use HTTP GET, HEAD and POST methods. In the case of POST methods, only content types with the following values are supported: text/plain, application/x-www-form-urlencoded and multipart/form-data.
  • Preflighted requests. When the \"simple requests\" use case doesn\'t apply, a first request (with the HTTP OPTIONS method) is made to check what can be done in the context of cross-domain requests.

So in fact most of work must be done on the server side to return the CORS headers. The main one is the Access-Control-Allow-Origin one.

200 OK HTTP/1.1
(...)
Access-Control-Allow-Origin: *

To debug such issues, you can use developer tools within browsers (Network tab).

Regarding Angular2, simply use the Http object like any other requests (same domain for example):

return this.http.get(\'https://angular2.apispark.net/v1/companies/\')
           .map(res => res.json()).subscribe(
  ...
);


回答2:

For me it was another problem. This might be trivial for some, but it took me a while to figure out. So this answer might be helpfull to some.

I had my API_BASE_URL set to localhost:58577. The coin dropped after reading the error message for the millionth time. The problem is in the part where it says that it only supports HTTP and some other protocols. I had to change the API_BASE_URL so that it includes the protocol. So changing API_BASE_URL to http://localhost:58577 it worked perfectly.



回答3:

It is nothing you can do in the client side. I added @CrossOrigin in the controller in the server side and it works.

@RestController
@CrossOrigin(origins = \"*\")
public class MyController

Please refer to docs.

Lin



回答4:

In my experience the plugins worked with http but not with the latest httpClient. Also, configuring the CORS respsonse headers on the server wasn\'t really an option. So, I created a proxy.conf.json file to act as a proxy server.

Read more about this here: https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md

below is my prox.conf.json file

{
  \"/posts\": {
    \"target\": \"https://example.com\",
    \"secure\": true,
    \"pathRewrite\": {
    \"^/posts\": \"\"
  },
    \"changeOrigin\": true
  }
}

I placed the proxy.conf.json file right next the the package.json file in the same directory

then I modified the start command in the package.json file like below

\"start\": \"ng serve --proxy-config proxy.conf.json\"

now, the http call from my app component is as follows

return this._http.get(\'/posts/pictures?method=GetPictures\')
.subscribe((returnedStuff) => {
  console.log(returnedStuff);
});

Lastly to run my app, I\'d have to use npm start or ng serve --proxy-config proxy.conf.json



回答5:

@RestController
@RequestMapping(value = \"/profile\")
@CrossOrigin(origins=\"*\")
public class UserProfileController {

SpringREST provides @CrossOrigin annotations where (origins=\"*\") allow access to REST APIS from any source.

We can add it to respective API or entire RestController.



回答6:

One of the way to enable cross domain request on local chrome browser :

  1. Create a short cut of google chrome.
  2. Properties -> append \"--disable-web-security --user-data-dir\" at the end of target.
  3. Close or kill all process of google chrome.
  4. Restart and hit the UI url.

Now UI and API running on different ports will be able to work together. I hope this helps.

If you are looking for an example of Cross-domain request . I\'ll put it in fragments for you to get enough idea.

  • Angular Client : http://localhost:4200/login
  • Spring web-api to validate a User :http://localhost:8091/SpringWebService/login\'

Angular Client

user.service.ts to call the SpringWebservice.

 /** POST: Validates a user for login from Spring webservice */
      loginUrl = \'http://localhost:8091/SpringWebService/login\';  // URL to web api

     validUser (user: User): Observable<User> {
        return this.http.post<User>(this.loginUrl, user, httpOptions)
       .pipe(
           catchError(this.handleError(\'Login User\', user))
  );
}

const httpOptions = {
  headers: new HttpHeaders({
    \'Content-Type\':  \'application/json;charset=utf-8\',
    \'Authorization\': \'my-auth-token\'
  })
};

login.component.html: to accept the user Name and pwd.

<form (ngSubmit)=\"onSubmit(loginForm)\" #loginForm=\"ngForm\">
    <!-- //ngModel is a must for each form-control  -->
  <!-- 1st group -->
  <div class=\"form-group\">
        <label for=\"name\">Name</label>
        <input type=\"text\" class=\"form-control\" id=\"name\" 
                required name=\"name\"  ngModel #name=\"ngModel\"> 

        <div [hidden]=\"name.valid || name.pristine\"
                class=\"alert alert-danger\">
             Name is required
        </div>
  </div> 
  <!-- 2nd group -->
  <div class=\"form-group\">
      <label for=\"pwd\">Password</label>
      <input type=\"text\" class=\"form-control\" id=\"pwd\"
            name=\"pwd\" #pwd required ngModel>
  </div>   

  <button type=\"submit\" class=\"btn btn-success\" [disabled]=\"!loginForm.valid\">Submit</button>

</form>

login.component.ts: calls and subscribes validUser method of user.service.

userModel : User;
onSubmit(loginForm : NgForm) { 
this.submitted = true; 
console.log(\"User : \"+loginForm.value.name + \" Valid :\"+loginForm.valid)

this.userModel.loggedIn= false;
this.userModel=new 
User(loginForm.value.name.trim(),loginForm.value.pwd.trim())
// Passing the userModel to Service method to invoke WebAPI
this.userService.validUser(this.userModel).subscribe(user=>
    {
      if(user.loggedIn == false){
        console.log(\"Invalid User/PWD\");

       }
      else{
        this.userService.changeUser(this.userModel);
        this.router.navigate([\'/home\']);
      }
  }
);

user.ts: model.

export class User {

constructor(
    public  name : String,
    public  pwd : String,
    public  email ?: String, //optional
    public  mobile ? : number,//\"\"
    public  loggedIn : boolean = false
){  }
}

Spring Webservice.

package com.rest;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
// This annotation opens door for cross-domain(Cross-origin resource sharing (CORS)) from any host
@CrossOrigin(origins=\"*\") 
public class MainController {

     @RequestMapping(value=\"/login\", method=RequestMethod.POST)
     public User validUser(@RequestBody User user){


         BaseResponse response = new BaseResponse();

         if(user.getName().equalsIgnoreCase(\"shaz\") && user.getPwd().equals(\"pwd\")){

             user.setLoggedIn(true);
         }
         else{

             user.setLoggedIn(false);

         }
         return user;

     }
}

Now when you pass name as \"shaz\" and pwd as \"pwd\" in the form and hit submit,it gets validated from the SpringWebService and the loggedIn flag is set to true and the user entity is returned in response. Based on the loggedIn status from response,the user is redirected to home page or an error is thrown.

Login Page and Network Details \"Login

\"Network

Note: I have not shared the complete setup and code

Refer this: https://shahbaazdesk.wordpress.com/2018/04/03/angular5-with-spring-webservice/



回答7:

Many long (and correct) answers here. But usually you won\'t do these things manually - at least not when you set up your first projects for development (this is where you usually stumble upon these things). If you use koa for the backend: use koa-cors. Install via npm...

npm install --save koa-cors

...and use it in the code:

const cors = require(\'koa-cors\');
const Koa = require(\'koa\');
const app = new Koa();
app.use(cors());

problem solved.