Angular2 - Paramètres de requête Http POST

91

J'essaye de faire une demande POST mais je n'arrive pas à la faire fonctionner:

testRequest() {
      var body = 'username=myusername?password=mypassword';
      var headers = new Headers();
      headers.append('Content-Type', 'application/x-www-form-urlencoded');

      this.http
        .post('/api',
          body, {
            headers: headers
          })
          .subscribe(data => {
                alert('ok');
          }, error => {
              console.log(JSON.stringify(error.json()));
          });
}

Je veux essentiellement répliquer cette requête http (pas ajax) comme si elle était originaire d'un formulaire html:

URL: / api

Paramètres: nom d'utilisateur et mot de passe

Christophe
la source
Jetez un œil à ce stackoverflow.com/a/34758630/5043867 et stackoverflow.com/a/34823818/5043867 cela vous expliquera tout sur la requête POST en profondeur!
Pardeep Jain
@PardeepJain je n'essaye pas de consommer une API. Juste pour simuler un POST créé par un formulaire html.
Christopher
Vérifiez également ici, publiez un fichier avec user_nameet password, stackoverflow.com/a/45879409/2803344
Belter

Réponses:

49

Je pense que le corps n'est pas correct pour un application/x-www-form-urlencodedtype de contenu. Vous pouvez essayer d'utiliser ceci:

var body = 'username=myusername&password=mypassword';

J'espère que ça vous aide, Thierry

Thierry Templier
la source
oui avec ce type de contenu dans l'en-tête, c'est la seule solution passant des valeurs "à l'ancienne" au lieu de la chaîne json
Nather Webber
Ce n'est pas une bonne réponse. Utilisez plutôt URLSearchParams, comme mentionné ci-dessous, avec plus de votes positifs.
Mick
Aux personnes du futur issues d'une recherche Google, ce n'est pas la meilleure réponse (pas de mal à Thierry! Votre réponse est toujours techniquement correcte :)). La réponse de V Stoykov est à ce jour la plus exacte. ps assurez-vous import { URLSearchParams } from "@angular/http"et non celui par défaut, donc 1) vous n'avez pas besoin de le faire .toStringdessus, et 2) vous n'avez pas besoin de définir le type de contenu. Angular l' inférera automatiquement pour vous (voir github.com/angular/angular/blob/4.4.4/packages/http/src/… )
Eran Medan
Salut ! si je veux passer le service de poste avec en-tête -> type de contenu comme 'application / json' ce que je dois passer dans le corps .... j'essaie de passer l'objet json mais cela ne fonctionne pas correctement ...
VjyV
107

Mise à jour pour Angualar 4.3+

Maintenant, nous pouvons utiliser à la HttpClientplace deHttp

Le guide est ici

Exemple de code

const myheader = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
let body = new HttpParams();
body = body.set('username', USERNAME);
body = body.set('password', PASSWORD);
http
  .post('/api', body, {
    headers: myheader),
  })
  .subscribe();

Obsolète

Ou vous pouvez faire comme ceci:

let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', username);
urlSearchParams.append('password', password);
let body = urlSearchParams.toString()

Mise à jour oct / 2017

De angular4 + , nous n'avons pas besoin headers, ni de .toString()trucs. Au lieu de cela, vous pouvez faire comme l'exemple ci-dessous

import { URLSearchParams } from '@angular/http';

Méthode POST / PUT

let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', username);
urlSearchParams.append('password', password);
this.http.post('/api', urlSearchParams).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
    )

Méthode GET / DELETE

    let urlSearchParams = new URLSearchParams();
    urlSearchParams.append('username', username);
    urlSearchParams.append('password', password);
    this.http.get('/api', { search: urlSearchParams }).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
    )

Pour le type de application/jsoncontenu JSON

this.http.post('/api',
      JSON.stringify({
        username: username,
        password: password,
      })).subscribe(
      data => {
        alert('ok');
      },
      error => {
        console.log(JSON.stringify(error.json()));
      }
      )
Frank Nguyen
la source
14
N'oubliez pas d'importer la classe URLSearchParamsimport { URLSearchParams } from "angular2/http"
Sebastian Hernandez
10
mon import est différent: import {URLSearchParams} de '@ angular / http';
dang
mais, il n'y a pas un moyen plus simple d'envoyer un objet de formulaire? Je n'ai vu aucun tutoriel utilisant URLSearchParams () pour envoyer un message pour un backend avec repos. comment font-ils? return this.http.post (this.actionUrl, body, {headers: this.headers}) .map ((response: Response) => response.json ()) .catch (this.handleError);
stackdave
Comment cela fonctionne avec les booléens? Obtenir une erreur disant que je ne peux pas ajouter des booléens ou des nombres, juste des chaînes (en append)
JohnAndrews
À propos de booléen, ce sujet peut peut-être vous aider à stackoverflow.com/questions/14774907/…
Frank Nguyen
41

Dans les versions ultérieures d'Angular2, il n'est pas nécessaire de définir manuellement l'en- Content-Typetête et d'encoder le corps si vous passez un objet du bon type commebody .

Vous pouvez simplement le faire

import { URLSearchParams } from "@angular/http"


testRequest() {
  let data = new URLSearchParams();
  data.append('username', username);
  data.append('password', password);

  this.http
    .post('/api', data)
      .subscribe(data => {
            alert('ok');
      }, error => {
          console.log(error.json());
      });
}

De cette façon, angular encodera le corps pour vous et définira le bon Content-Type tête .

PS N'oubliez pas d'importer URLSearchParamsdepuis @angular/httpou cela ne fonctionnera pas.

VStoykov
la source
2
@VStoykov cela ne fonctionne pas, vous devez .toString () sur les paramètres et vous devez spécifier le type de contenu, et j'utilise angular 4.0.3
Konrad
1
@ i'myourhuckleberry Cela devrait fonctionner même sur 4.0.3. Regardez le code source github.com/angular/angular/blob/4.0.3/packages/http/src/…
VStoykov
1
@VStoykov cela ne fonctionne pas pour moi et je l'ai signalé comme un bug sur Github
Konrad
1
D'ACCORD. Nvm J'ai dû l'importer depuis "@ angular / http" sinon il reconnaît le type mais ce n'est pas le type angular.
Konrad
1
@ i'myourhuckleberry l'importation était la première ligne de mon exemple, mais vous l'avez probablement manquée. À partir des types intégrés dans le navigateur, vous pouvez utiliser FormData, et angulaire sera défini Content-Typecomme multipart/form-dataqui fonctionne également.
VStoykov
10

donc juste pour en faire une réponse complète:

login(username, password) {
        var headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        let urlSearchParams = new URLSearchParams();
        urlSearchParams.append('username', username);
        urlSearchParams.append('password', password);
        let body = urlSearchParams.toString()
        return this.http.post('http://localHost:3000/users/login', body, {headers:headers})
            .map((response: Response) => {
                // login successful if there's a jwt token in the response
                console.log(response);
                var body = response.json();
                console.log(body);
                if (body.response){
                    let user = response.json();
                    if (user && user.token) {
                        // store user details and jwt token in local storage to keep user logged in between page refreshes
                        localStorage.setItem('currentUser', JSON.stringify(user)); 
                    }
                }
                else{
                    return body;
                }
            });
    }
dang
la source
1
[ts] Argument de type '{headers: RequestOptions; } 'n'est pas attribuable au paramètre de type' RequestOptionsArgs '
Sonic Soul
2
@Sonic Soul c'est juste: .. post ('/ api', body, headers) ... without {} around headers
Guenther
5

Ces réponses sont toutes obsolètes pour ceux qui utilisent HttpClient plutôt que Http. Je commençais à devenir fou en pensant: "J'ai fait l'importation d'URLSearchParams mais cela ne fonctionne toujours pas sans .toString () et l'en-tête explicite!"

Avec HttpClient, utilisez HttpParams au lieu de URLSearchParams et notez la body = body.append()syntaxe pour obtenir plusieurs paramètres dans le corps puisque nous travaillons avec un objet immuable:

login(userName: string, password: string): Promise<boolean> {
    if (!userName || !password) {
      return Promise.resolve(false);
    }

    let body: HttpParams = new HttpParams();
    body = body.append('grant_type', 'password');
    body = body.append('username', userName);
    body = body.append('password', password);

    return this.http.post(this.url, body)
      .map(res => {
        if (res) {          
          return true;
        }
        return false;
      })
      .toPromise();
  }
333Mats
la source
merci pour la solution ci-dessus. Mais lors de l'exécution de ng build --prod, mes paramètres de corps ressemblent à "{" params ": {" rawParams ":" "," queryEncoder ": {}," paramsMap ": {}}}:". Y a-t-il une solution de contournement.
Hemanth Poluru
4

Si quelqu'un a du mal avec la version angulaire 4+ (la mienne était 4.3.6) . C'était l'exemple de code qui a fonctionné pour moi.

Ajoutez d'abord les importations requises

import { Http, Headers, Response, URLSearchParams } from '@angular/http';

Ensuite, pour la fonction api. C'est un exemple de connexion qui peut être modifié selon vos besoins.

login(username: string, password: string) {
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    let urlSearchParams = new URLSearchParams();
    urlSearchParams.append('email', username);
    urlSearchParams.append('password', password);
    let body = urlSearchParams.toString()

    return this.http.post('http://localhost:3000/api/v1/login', body, {headers: headers})
        .map((response: Response) => {
            // login successful if user.status = success in the response
            let user = response.json();
            console.log(user.status)
            if (user && "success" == user.status) {
                // store user details and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify(user.data));
            }
        });
}
PC Krishnadas
la source
0

J'avais des problèmes avec chaque approche utilisant plusieurs paramètres, mais cela fonctionne assez bien avec un seul objet

api:

    [HttpPut]
    [Route("addfeeratevalue")]
    public object AddFeeRateValue(MyValeObject val)

angulaire:

var o = {ID:rateId, AMOUNT_TO: amountTo, VALUE: value};
return this.http.put('/api/ctrl/mymethod', JSON.stringify(o), this.getPutHeaders());


private getPutHeaders(){
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return new RequestOptions({
        headers: headers
        , withCredentials: true // optional when using windows auth
    });
}
Sonic Soul
la source
1
Le problème de OP est le type de contenu de l'application / x-www-form-urlencoded, votre réponse est un problème totalement différent.
Christian Ulbrich
0
angular: 
    MethodName(stringValue: any): Observable<any> {
    let params = new HttpParams();
    params = params.append('categoryName', stringValue);

    return this.http.post('yoururl', '', {
      headers: new HttpHeaders({
        'Content-Type': 'application/json'
      }),
      params: params,
      responseType: "json"
    })
  }

api:   
  [HttpPost("[action]")]
  public object Method(string categoryName)
Muniyan
la source
Bonjour et bienvenue sur Stackoverflow. Merci d'avoir répondu à cette question, mais le simple fait de publier un bloc de code est difficile à comprendre pour l'OP ou quiconque rencontrera cette question à l'avenir. Seriez-vous en mesure de modifier votre question et de donner une (brève) explication du problème que vous avez résolu et de la manière dont vous l'avez résolu, pour nous aider à mieux comprendre votre solution?
Plutien
1
Salut @Plutian quand j'ai passé la valeur sur le 2ème paramètre de la demande de publication, il m'a renvoyé les valeurs nulles sur l'api, alors j'ai passé ce 2ème paramètre en tant que chaîne vide et j'ai passé les valeurs sur la propriété params du 3ème paramètre, donc cette méthode a fonctionné pour moi
Muniyan
-2

J'ai atterri ici alors que j'essayais de faire une chose similaire. Pour un type de contenu application / x-www-form-urlencoded, vous pouvez essayer de l'utiliser pour le corps:

var body = 'username' =myusername & 'password'=mypassword;

avec ce que vous avez essayé de faire, la valeur assignée au corps sera une chaîne.

Adongo
la source
Comme Joshua l'a souligné, ce n'est ni JavaScript ni TypeScript valides. Je pense que vous vouliez dire exactement la réponse actuellement acceptée.
Christian Ulbrich