Envoi d'un fichier CSV via un post API

Request description

Bonjour, je souhaite réaliser une requête POST via une API externe à Renault comportant 2 champs: Currency_Exchange_Rates_Accrued (fichier CSV) et jwt (token sous forme de string). J’ai crée une méthode en rajoutant l’utilisation de proxy (que je collerai plus bas dans le poste), mais je tombe systématiquement sur une erreur 404: {“code”:404,“message”:“Not Found”}. Néanmoins, sur Postman, le post fonctionne normalement.

Steps to reproduce

public static JSONObject postCsvJSON(Grant grant, String url, String filePath, String jwtToken) {
  setLogLevel(grant, Level.INFO);
  Unirest.config().clientCertificateStore(CERTIFICATE_PATH, CERTIFICATE_PASSWORD);
  HttpRequestWithBody request = Unirest.post(url);
  boolean needProxy = !url.startsWith(Grant.getSystemAdmin().getContextURL()) && !Grant.getSystemAdmin().getContextURL().endsWith("simplicite.io");
  if (needProxy) {
    String proxyData = Grant.getSystemAdmin().getParameter("RENAULT_PROXY");
    String proxyHost = null;
    String proxyPort = null;
    if (StringUtils.isNotBlank(proxyData)) {
      String[] proxyDataPart = proxyData.split(",");
      proxyHost = proxyDataPart[0].trim();
      proxyPort = proxyDataPart[1].trim();
    } else {
      if (url.startsWith("https")) {
        proxyHost = System.getProperty("https.proxyHost");
        proxyPort = System.getProperty("https.proxyPort");
      } else {
        proxyHost = System.getProperty("http.proxyHost");
        proxyPort = System.getProperty("http.proxyPort");
      }
    }
    request.proxy(proxyHost, Integer.parseInt(proxyPort));
  }

  final kong.unirest.HttpResponse < String > response;

  File file = new File(filePath);
  response = request.header(HttpHeaders.CONTENT_TYPE, "multipart/form-data")
    .field("Currency_Exchange_Rates_Accrued", file)
    .field("jwt", jwtToken)
    .asString();

  if (response.isSuccess()) {
    return new JSONObject(response.getBody());
  } else {
    return new JSONObject().put("code", response.getStatus()).put("message", response.getStatusText());
  }
}

Technical information

Instance /health
[Platform]
Status=OK
Version=5.2.38
BuiltOn=2023-04-20 10:56
Git=5.2/66dd3f848850f0ba670a5f92674282285b3d3341
Encoding=UTF-8
EndpointIP=172.17.0.6
EndpointURL=http://902b2556b6d5:8080
TimeZone=Europe/Paris
SystemDate=2023-05-03 11:24:52
Simplicité logs
---paste the content of the **relevant** server-side logs---
Browser logs
---paste content of the **relevant** browser-side logs---
Other relevant information

----E.g. type of deployment, browser vendor and version, etc.----

Je n’ai pas l’impression qu’il s’agisse d’un pb Simplicité mais plutôt dans l’usage de la librairie tierce Unirest sur laquelle nous n’avons pas d’expertise particulière.

Peut être devriez vous plutôt demander du support sur un forum dédié à cette librairie ?

Typiquement il me semble qu’il n’y a pas besoin de forcer le content type en fct des méthodes appelées. mais, à nouveau, nous n’avons pas d’expertise particulière sur cette librairie tierce. Personnellement je l’ai déjà utilisée dans un projet métier pour faire des appels GET et POST et je n’ai pas eu de pb.

Peut être que si vous exécutez ce code en debug pas à pas en dehors de Simplicité vous trouverez en quoi ça génère un appel HTTP différent de ce que vous faites dans Postman.

Bonjour,
En essayant ma méthode hors Simplicité, je suis effectivement tombé sur des erreurs liées à l’utilisation de la librairie. J’ai donc continué à travailler sur mon pc personnel, et je suis arrivé au développement de la méthode ci-dessous:

		  CloseableHttpClient httpClient = HttpClientBuilder.create().build();
			RequestConfig config = RequestConfig.custom()
			.setConnectTimeout(5000)
			.setSocketTimeout(5000)
			.build();
			
	        // Envoi requête POST 
	        HttpPost postRequest1 = new HttpPost(urlTaxVision);
	        
	        // Application du RequestConfig
	        postRequest1.setConfig(config);
	        
	        MultipartEntityBuilder builder1 = MultipartEntityBuilder.create();
	        builder1.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
	        builder1.addBinaryBody("Currency_Exchange_Rates_Accrued", new File(filePath), ContentType.DEFAULT_BINARY, fileName);
	        builder1.addTextBody("jwt", jwtTaxVision, ContentType.DEFAULT_TEXT);
	        HttpEntity entity1 = builder1.build();
	        postRequest1.setEntity(entity1);
	        try {
	            HttpResponse response1 = httpClient.execute(postRequest1);
	            AppLog.info("| REPONSE ALGONOMIA API : " + EntityUtils.toString(response1.getEntity()) + "'", getGrant());
	        } catch (IOException e) {
	            ByteArrayOutputStream baos = new ByteArrayOutputStream();
			    PrintStream ps = new PrintStream(baos);
			    e.printStackTrace(ps);
			    String stackTrace = baos.toString();
	            AppLog.info("| ERREUR REPONSE ALGONOMIA API : " + stackTrace + "'", getGrant());
	        }

Ce code fonctionne parfaitement et l’API arrive bien à acheminer le fichier CSV de out en bout. Mais en copiant-collant ce code dans Simplicité, je tombe sur une erreur 443. Voici ce que j’ai pu relever dans les logs:

     at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151)
     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
     at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
     at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
     at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
     at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
     at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
     at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
     at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
     at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
     at com.simplicite.adapters.RenaultForex.MonthlyActualTSV.setBusinessObjects(MonthlyActualTSV.java:289)
     at com.simplicite.commons.RenaultForex.ForexCommonAdapter.postProcess(ForexCommonAdapter.java:79)
     at com.simplicite.util.Adapter.applyAdapter(Adapter.java:385)
     at com.simplicite.util.engine.Interface.importData(Interface.java:547)
     at com.simplicite.util.engine.Interface.importADP(Interface.java:483)
     at com.simplicite.util.engine.IntegrationDirect.importADP(IntegrationDirect.java:203)
     at com.simplicite.util.Integration.importADP(Integration.java:452)
     at com.simplicite.webapp.servlets.AbstractIOServlet.doPost(AbstractIOServlet.java:484)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:555)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
     at com.simplicite.webapp.filters.RewriteFilter.doFilter(RewriteFilter.java:68)
     at com.simplicite.webapp.filters.AbstractFilter.doFilter(AbstractFilter.java:49)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
     at com.simplicite.webapp.filters.HTTPHeadersFilter.doFilter(HTTPHeadersFilter.java:39)
     at com.simplicite.webapp.filters.AbstractFilter.doFilter(AbstractFilter.java:49)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
     at com.simplicite.webapp.filters.AuthMethodFilter.doFilter(AuthMethodFilter.java:220)
     at com.simplicite.webapp.filters.AbstractFilter.doFilter(AbstractFilter.java:49)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:155)
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
     at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:673)
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
     at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389)
     at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
     at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
     at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
     at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
     at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
     at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
     at java.base/java.lang.Thread.run(Thread.java:833)
    Caused by: java.net.SocketTimeoutException: Connect timed out
     at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:546)
     at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
     at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
     at java.base/java.net.Socket.connect(Socket.java:633)
     at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:368)
     at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
     ... 53 more

Est-ce que vous auriez une idée d’où proviendrai l’erreur? Peut-être un proxy particulier à utiliser vu que l’API utilisée est externe à Renault. Auriez-vous une quelconque expertise concernant ce type d’erreur ou tout simplement me conseillerez-vous de me tourner vers un DevOps pour investiguer?
Je vous remercie d’avance pour les solutions que vous m’apporterez.

AISSANI Said

Ca semble être un pb de “tuyauterie” réseau => le service que vous tentez d’appeler n’est sans doute pas accessible depuis le serveur où tourne Simplicité, pb de firewall ? de proxy ? autre…

C’est la réflexion que j’ai eu en voyant l’erreur, je vais regarder cela de plus près avec un DevOps.
Je vous en remercie.

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.