2
votes

Demande de poste angulaire 7 avec corps et en-tête

J'essaye de faire une demande de publication avec le corps et l'en-tête. Voici quelques-unes des variantes que j'ai connues, mais pour la plupart, j'obtiens une erreur sur le serveur disant que le paramètre «clé» n'a pas été transmis.

J'ai essayé cette api dans le facteur et cela fonctionne Là. Voici comment j'ai défini l'en-tête de méthode dans Java / Spring Boot:

timestamp: "2019-01-30T04:30:40.721+0000", status: 400, error: "Bad Request",…}
error: "Bad Request"
message: "Required String parameter 'key' is not present"
path: "/jira/getIssue"
status: 400
timestamp: "2019-01-30T04:30:40.721+0000"
trace: "org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'key' is not present

Voici les variations de mes angulaires:

public getJiraIssue(key: string): Observable<any> {

    let headers = new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': this.idToken });
    let options = { headers: headers };

    const paramsA = new URLSearchParams();
    paramsA.set('key', key);
    let params = new HttpParams().append('key', key);
    // return this.http.post(this.urlEnvironment.jiraGetIssue(), params, this.getHeaders());
    console.log("headers: ", this.getHeaders());
    // let obj = {
    //   key: key
    // }

    var headersA = new Headers();
    headers.append('Authorization', this.idToken);

    let body = new HttpParams()
    .set('key', key);

    return this.http.post(this.urlEnvironment.jiraGetIssue(), body, {headers: headers});
    // return this.http.post(this.urlEnvironment.jiraGetIssue(), null, {headers: this.getHeaders(), params: params});
  }

Il semble que le corps soit envoyé:

 entrez la description de l'image ici

Mais voici l'erreur que j'ai eue:

@RequestMapping(value = "/getIssue", method = RequestMethod.POST)
public IssuePojo getIssue(@RequestParam("key") String key, HttpServletRequest request) {


5 commentaires

OK: vous êtes donc en mesure d'interroger Jira à partir de Postman, vous savez donc a) quels devraient être les en-têtes HTTP ('Content-Type': 'application / json', et 'Authorization': XYZ), et vous savez ce que le corps doit être (JSON comme ceci: developer.atlassian. com / serveur / jira / plateforme /… ). Jusqu'ici tout va bien. Q: Qui interroge Jira: votre frontal JS / Angular ou votre backend de démarrage Java / Spring? Q: Avez-vous regardé le HTTP envoyé (Fiddler ou Wireshark)?


Je disais que j'ai vérifié que mon API Java fonctionne via Postman. Java interroge Jira


Q: Pouvez-vous interroger Jira n’importe où ? Java? Facteur? Boucle? Q: Avez-vous confirmé l'apparence du corps HTTP devrait ? Je suppose que cela devrait peut-être être JSON (comme ici ), et PAS une chaîne comme "key = WJC-7". SUGGESTION: Vérifiez le format du message.


Oui, l'API fonctionne correctement. J'ai testé ma méthode de différentes manières, depuis Java et Postman. Si je retire mon Servlet de la méthode, cela fonctionne.


voir ceci: stackoverflow.com/questions/58601675/...


4 Réponses :


2
votes

HttpParams () sont utilisés pour ajouter le paramètre de requête sting à l'URL de la requête si vous en avez besoin, puis vérifiez d'abord si cela est ajouté dans la requête des outils de développement qui est faite si cela est là, alors il y a quelque chose qui ne va pas du côté de l'API


7 commentaires

Non, je n'ai pas besoin des paramètres d'URL. J'ai besoin des paramètres à travers le corps.


Si je ne me trompe pas, @RequestParam en java voulait également obtenir les données de la chaîne de requête uniquement comme le lien ci-dessous suggère reversecoding.net/...


Ok, alors qu'est-ce que je fais de mal? Pourquoi cela fonctionnerait-il du facteur? Que dois-je changer alors?


Si vous voulez le transmettre à body, essayez le code ci-dessous let body = {'key', key}; return this.http.post (this.urlEnvironment.jiraGetIssue (), body, {headers: headers});


Je ne suis pas familier avec java mais comme vous l'avez dit, cela fonctionne avec post man pouvez-vous vérifier comment post man fait la demande si elle est envoyée dans le corps, puis essayez ci-dessus de poster une autre question dans le forum java pour résoudre ce problème


J'ai déjà essayé cela, si vous regardez dans mon code commenté, j'ai essayé de laisser obj = ... Exactement comme vous le dites


J'ai également étiqueté la question pour Spring Boot.



0
votes

 entrez la description de l'image ici Utilisez cette classe de service HHTP pour envoyer des paramètres dans le corps et vous pouvez également envoyer des en-têtes

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable, empty } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';


@Injectable({
  providedIn: 'root'
})
export class HttpService {
  constructor(private http: HttpClient) {
  }

  private getHeaders(headersConfig?: object): HttpHeaders {
    return new HttpHeaders({
      'Content-Type': 'application/json',
      ...headersConfig,
    });
  }

  get(url: string, params: HttpParams = new HttpParams(), headers: Object): Observable<any> {
    let finalHeaders = this.getHeaders();
    if (headers) {
      for (let key in headers) {
        finalHeaders = finalHeaders.append(key, headers[key]);
      }
    }
    return this.http.get(
      url,
      { headers: finalHeaders, params }
    ).pipe(timeout(10000)).pipe(catchError(this.handleError('Get request')));
  }

  put(url: string, body: Object = {}, headers: Object): Observable<any> {
    let finalHeaders = this.getHeaders();
    if (headers) {
      for (let key in headers) {
        finalHeaders = finalHeaders.append(key, headers[key]);
      }
    }
    return this.http.put(
      url,
      body,
      { headers: finalHeaders }
    ).pipe(timeout(10000)).pipe(catchError(this.handleError<any>('put request')));
  }

  post(url: string, body: Object = {}, headers: Object): Observable<any> {
    let finalHeaders = this.getHeaders();
    if (headers) {
      for (let key in headers) {
        finalHeaders = finalHeaders.append(key, headers[key]);
      }
    }
    return this.http.post(
      url,
      body,
      { headers: finalHeaders }
    ).pipe(timeout(10000)).pipe(catchError(this.handleError<any>('post request')));
  }

  /**
 * Handle Http operation that failed.
 * Let the app continue.
 * @param operation - name of the operation that failed
 * @param result - optional value to return as the observable result
 */
  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      return empty();//of(result as T);
    };
  }
}


11 commentaires

Je ne veux pas combiner mes paramètres avec mon en-tête. Je veux garder les deux séparés


Si vous passez l'en-tête comme nul, la méthode de publication n'ajoutera pas d'en-tête à la demande.


Mais j'ai besoin d'envoyer les deux choses, les en-têtes et le corps


this.httpService.put (yourURL, bodyData, headerData). Vous ne pouvez envoyer que bodyParam en définissant headerData = null.


si bodyData et headerData ne sont pas nuls, les deux seront envoyés.


C'est ça la question. J'ai également montré la capture d'écran de la console du développeur indiquant que les deux étaient envoyés. Alors pourquoi Spring Boot rejette-t-il?


Je pense qu'il y a un problème dans la manière dont vous envoyez les paramètres. Les paramètres ne sont pas présentés sous forme d'objet JSON. La charge utile de réponse doit s'afficher comme {"key": "WJC-7"}. Vérifiez l'image ci-jointe.


Oui, je suis toujours confronté à des problèmes


continuons cette discussion dans le chat .


Je peux envoyer json, ça marche. Il correspond correctement à pojo. Mais je ne veux pas continuer à créer des Pojos pour 1, 2 ou 3 arguments.


Je n'ai pas beaucoup d'idée pour Spring boot, mais pouvez-vous essayer de créer un seul POJO pour de telles demandes et garder les paramètres facultatifs, de sorte que chaque demande soit analysée.



0
votes

Donc, la clé est 'Content-Type': 'application / json', Puisque j'envoie json, alors du côté serveur, il s'attend à le mapper à un objet. J'ai également réussi à le faire fonctionner avec une chaîne, mais je dois ensuite analyser la chaîne moi-même sur le serveur, ce qui n'est pas ce que je cherche à faire.

Donc, 'Content-Type': 'text / plain ', => correspond à => @RequestBody String key

Et ' Content-Type ':' application / x-www-form -urlencoded; charset = UTF-8 ', => correspond à => @RequestParam Clé de chaîne, @RequestParam Test de chaîne,

Et ainsi l'appel de poste de Angular ressemblera à ceci:

const httpBody = new HttpParams()
      .set('key', 'key')
      .set('test', 'test');
    return this.http.post(endPoint, httpBody, this.getArgHeaders());

  private getArgHeaders(): any {
      const httpOptions = {
        headers: new HttpHeaders({
          'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
        })
      };
      return httpOptions;
  }


0 commentaires

1
votes

OK, je crois comprendre que vous avez un frontal JS / Angular 7. Il parle à un back-end Java / Spring Boot, qui à son tour interroge Jira:

public class Todo {
    private long id;
    private String username;
    private String description;
    private Date targetDate;
    private boolean isDone;
    ...

Correct pour l'instant?

Il semble que vous puissiez interroger Jira avec Postman (demande 2, réponse 3), c'est exact?

Le problème est que votre get HTTP 400: "Le paramètre de chaîne obligatoire 'key' n'est pas présent" lorsque Angular interroge Spring Boot (requête 1), correct?

C'est ce que j'essayais de demander dans mes commentaires ci-dessus. Le problème est clairement que la charge utile de votre message, "key = WJC-7", n'est pas JSON valide. Donc la requête échoue.

Sur la base de ce que vous avez partagé, je fais beaucoup de "suppositions" ici. Néanmoins:

SUGGESTION:

  1. Demandez à Angular de créer l'objet: let obj = {key: key}; , comme vous le faisiez au départ.

  2. Assurez-vous qu'il est complet (j'imagine que l'API Jira a besoin de plus qu'une simple "clé").

  3. Assurez-vous que l'objet Angular que vous envoyez correspond - champ par champ - à l'objet Java attendu par le contrôleur Spring Boot. Spring Boot devrait automatiquement sérialiser / désérialiser en JSON.

  4. Demandez à Angular d'envoyer l'objet (en tant que "données"). Votre "message payload"! = "Msg headers".

  5. Soyez SÛR d'examiner les charges utiles envoyées et reçues à chaque étape du processus (1, 2, 3 et 4 ci-dessus). Vous pouvez le faire avec Fiddler, avec Wireshark ou avec la journalisation de trace.

'J'espère que cela aide!

PS: Voici un exemple hypothétique d'un contrôleur Java Spring Boot qu'un client Angular pourrait appeler:

...
@RestController
@CrossOrigin(origins = "http://localhost:4200")
public class TodoResource {

    @Autowired
    private TodoHardcodedService todoService;

    // GET All todos
    @GetMapping("/users/{username}/todos")
    public List<Todo> getAllTodos(@PathVariable String username) {
        return todoService.findAll();
    }
...

Et voici l'exemple d'objet Java "Todo" correspondant:

    Angular       SpringBoot         Jira
   --------- (1)  ----------- (2) ----------
   (service) --> (controller) --> (Jira API)
             <--              <--
             (4)              (3)


3 commentaires

Oui, mais que faire si je ne dois envoyer que deux arguments? Seulement 3, seulement 4? Peut-être qu'à 4 arguments, je pourrais commencer à créer des Pojos en Java. Mais 1, 2 ou 3 arguments, je ne devrais pas avoir à continuer à créer Pojos.


Votre plainte initiale était "cela ne fonctionne pas". Nous savons maintenant pourquoi. J'espère que ce qui précède a été utile. Vous avez maintenant une nouvelle "exigence": vous aimeriez des "arguments variables". C'est un "peut-faire". C'est aussi un problème distinct. Vous avez différentes options ... mais traitons une chose à la fois. Quick'n'dirty, solution temporaire: déclarez simplement toutes vos propriétés dans le POJO, et laissez le contrôleur ignore celles que le client n'envoie pas.


PS: Vous pourriez également être intéressé par Lombok