• Recent
    • Tags
    • Popular
    • Register
    • Login

    Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

    Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website Mango 5 Documentation Website

    CRUD for data sources

    Dashboard Designer & Custom AngularJS Pages
    4
    10
    2.9k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      hrivers
      last edited by hrivers

      I'm having issues with the cURL call to create a data source. This is the code I'm using-- the authentication part has worked in other areas, but now. while I'm getting TRUE for the second curl_execl, I'm getting an HTTP status of 403. If I set CURLOPT_POST to 0 I get data returned correctly for a GET, so I seem to be authenticated just fine. It seems that the POST is the part I'm having problems with. I've used the swagger page with no issue and have created my $devices array directly from data that worked there (changing the xid). I'm not sure what's wrong with the POST that it doesn't work.

      $curl = curl_init();

      $headers = array(
      'Accept: application/json',
      'Accept-Encoding: gzip',
      'Accept-Language: en-US,en;q=0.5',
      'Connection: keep-alive',
      'Cache-Control: no-cache',
      'password: admin',
      'logout: true'
      );

      curl_setopt_array($curl, array(
      CURLOPT_RETURNTRANSFER => TRUE,
      CURLOPT_HEADER => TRUE,
      CURLOPT_VERBOSE => TRUE,
      CURLOPT_HTTPHEADER => $headers,
      CURLOPT_URL => 'http://<url>:8080/rest/v1/login/admin'
      ));

      $response = curl_exec($curl);
      $tmp = explode('XSRF-TOKEN=', $response);
      $tmp = explode(';',$tmp[1]);
      $xsrf_token = $tmp[0];
      $tmp = explode('MANGO8080=', $response);
      $tmp = explode(';',$tmp[1]);
      $mango8080 = $tmp[0];
      curl_close($curl);

      $curl = curl_init();

      $headers = array(
      'Accept: application/json',
      'Content-Type: application/json', //multipart/form-data
      'Connection: keep-alive',
      'Cache-Control: no-cache',
      'Cookie: XSRF-TOKEN='.$xsrf_token.';MANGO8080='.$mango8080
      );

      curl_setopt_array($curl, array(
      //CURLOPT_RETURNTRANSFER => TRUE,
      CURLOPT_VERBOSE => TRUE,
      CURLOPT_HTTPHEADER => $headers,
      CURLOPT_POST => TRUE,
      CURLOPT_POSTFIELDS => $device, //HERE either $device or http_build_query($device) which yields 'xid=DS_HR_POST&name=HR_TEST_MIN_VARS_POST&modelType=SNMP&host=<url>'
      CURLOPT_URL => 'http://<url>:8080/rest/v1/data-sources'
      ));

      $response = curl_exec($curl);
      error_log(json_encode(curl_getinfo($curl)));
      error_log($response);
      curl_close($curl);

      curl_getinfo printout:

      {"url":"http://<url>.:8080/rest/v1/data-sources","content_type":null,"http_code":403,"header_size":291,"request_size":359,"filetime":-1,"ssl_verify_result":0,"redirect_count":0,"total_time":0.004956,"namelookup_time":7.7e-5,"connect_time":0.000631,"pretransfer_time":0.000642,"size_upload":0,"size_download":0,"speed_download":0,"speed_upload":0,"download_content_length":0,"upload_content_length":473,"starttransfer_time":0.00491,"redirect_time":0,"certinfo":[]}

      $response printout: 1 this way, blank if CURLOPT_RETURNTRANSFER = TRUE

      G 1 Reply Last reply Reply Quote 0
      • G
        gary @hrivers
        last edited by

        @hrivers In my experience with the Mango API, sometimes you need to include the header 'x-xsrf-token' as well as the cookies.

        Try this modification:

        $headers = array(
        'Accept: application/json',
        'Content-Type: application/json', //multipart/form-data
        'Connection: keep-alive',
        'Cache-Control: no-cache',
        'Cookie: XSRF-TOKEN='.$xsrf_token.';MANGO8080='.$mango8080,
        'x-xsrf-token: ' . $xsrf_token             //ADDED
        );
        
        

        Gary

        H 1 Reply Last reply Reply Quote 0
        • H
          hrivers @gary
          last edited by

          @gary said in CRUD for data sources:

          'x-xsrf-token: ' . $xsrf_token

          That gives me a status 400 with the following message:

          {"message":"Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value\n at [Source: java.io.PushbackInputStream@2f3c2d0; line: 1, column: 3]","stackTrace":"com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1419)\ncom.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:508)\ncom.fasterxml.jackson.core.base.ParserBase.reportUnexpectedNumberChar(ParserBase.java:939)\ncom.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleInvalidNumberStart(UTF8StreamJsonParser.java:2487)\ncom.fasterxml.jackson.core.json.UTF8StreamJsonParser._parseNegNumber(UTF8StreamJsonParser.java:1245)\ncom.fasterxml.jackson.core.json.UTF8StreamJsonParser._nextTokenNotInObject(UTF8StreamJsonParser.java:777)\ncom.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:690)\ncom.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3090)\ncom.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3036)\ncom.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2206)\norg.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:221)\norg.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:208)\norg.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:197)\norg.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:147)\norg.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:125)\norg.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:78)\norg.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)\norg.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)\norg.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)\norg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)\norg.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)\norg.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)\norg.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)\norg.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)\norg.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)\norg.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)\njavax.servlet.http.HttpServlet.service(HttpServlet.java:707)\norg.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)\njavax.servlet.http.HttpServlet.service(HttpServlet.java:790)\norg.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)\norg.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)\norg.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:51)\norg.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)\norg.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)\norg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\norg.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)\norg.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:87)\ncom.serotonin.m2m2.web.filter.MangoShallowEtagHeaderFilter.doFilterInternal(MangoShallowEtagHeaderFilter.java:47)\norg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\norg.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)\norg.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)\norg.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\ncom.serotonin.m2m2.web.mvc.spring.security.CsrfHeaderFilter.doFilterInternal(CsrfHeaderFilter.java:41)\norg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124)\norg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)\norg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)\norg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\norg.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)\norg.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)\norg.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)\norg.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)\norg.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)\norg.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1668)\norg.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)\norg.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)\norg.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)\norg.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)\norg.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)\norg.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)\norg.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)\norg.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)\norg.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)\norg.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)\norg.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)\norg.eclipse.jetty.server.Server.handle(Server.java:524)\norg.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)\norg.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)\norg.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)\norg.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)\norg.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)\norg.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)\norg.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)\norg.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)\norg.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)\norg.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)\njava.lang.Thread.run(Thread.java:745)\n"}

          1 Reply Last reply Reply Quote 0
          • Jared WiltshireJ
            Jared Wiltshire
            last edited by

            As @gary has pointed out, you are running up against the CSRF protection. CRSF protection only affects POST requests which is why your GET request is working.

            You need to read the XSRF-TOKEN cookie which the server tells you to set and then send that back to the server with every request as a 'X-XSRF-TOKEN' header.

            We are going to make this easier in Mango 3.0 by implementing token authentication which will not require CSRF protection.

            Developer at Radix IoT

            H 1 Reply Last reply Reply Quote 0
            • H
              hrivers @Jared Wiltshire
              last edited by

              @Jared-Wiltshire When I modified my code to add that, I get an error stating there's an unexpected character in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value. Is this my xsrf token or an issue with the post data? My xsrf token is an alphanumeric string with hypens, and my device is defined as follows:

              $device = array(
              "xid" => "DS_HR_POST",
              "name" => "HR TEST MIN VARS POST",
              "modelType" => "SNMP",
              "host" => "<valid ip address>"
              );

              1 Reply Last reply Reply Quote 0
              • Jared WiltshireJ
                Jared Wiltshire
                last edited by

                @hrivers said in CRUD for data sources:

                @Jared-Wiltshire When I modified my code to add that, I get an error stating there's an unexpected character in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value. Is this my xsrf token or an issue with the post data? My xsrf token is an alphanumeric string with hypens, and my device is defined as follows:

                $device = array(
                "xid" => "DS_HR_POST",
                "name" => "HR TEST MIN VARS POST",
                "modelType" => "SNMP",
                "host" => "<valid ip address>"
                );

                Looks like an issue with the POST body, its a JSON parsing error.

                Developer at Radix IoT

                H 1 Reply Last reply Reply Quote 0
                • H
                  hrivers @Jared Wiltshire
                  last edited by

                  @Jared-Wiltshire I re-wrote my cURL query as follows:

                  $headers = array(
                  'Accept: application/json',
                  'Content-Type: multipart/form-data', //as opposed to application/json
                  'Connection: keep-alive',
                  'Cache-Control: no-cache',
                  'Cookie: XSRF-TOKEN='.$xsrf_token.';MANGO8080='.$mango8080,
                  'X-XSRF-TOKEN:'.$xsrf_token
                  );

                  		curl_setopt_array($curl, array(
                  			CURLOPT_RETURNTRANSFER => TRUE,
                  			CURLOPT_VERBOSE => TRUE,
                  			CURLOPT_HTTPHEADER => $headers,
                  			CURLOPT_POST => TRUE,
                  			CURLOPT_POSTFIELDS => http_build_query($device), //as opposed to $device
                  			CURLOPT_URL => 'http://<url>:8080/rest/v1/data-sources'
                  		));
                  

                  and in return I got a new error: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

                  Have you seen this before? Do you have any suggestions?

                  1 Reply Last reply Reply Quote 0
                  • phildunlapP
                    phildunlap
                    last edited by phildunlap

                    Hi hrivers,

                    Your Content-Type header should be application/json

                    Here is a successful POST to /rest/v1/data-sources creating an HTTP Receiver made through swagger, gotten from the network tab of the developer tools in the browser:

                    POST /rest/v1/data-sources HTTP/1.1
                    Host: localhost:8080
                    Connection: keep-alive
                    Content-Length: 534
                    Pragma: no-cache
                    Cache-Control: no-cache
                    Accept: application/json
                    Origin: http://localhost:8080
                    X-Xsrf-Token: [xsrf-token-value]
                    User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
                    Content-Type: application/json
                    Referer: http://localhost:8080/swagger/
                    Accept-Encoding: gzip, deflate, br
                    Accept-Language: en-US,en;q=0.8
                    Cookie: XSRF-TOKEN=[xsrf-token-value]; MANGO8080=[cookie-value]
                    
                    {
                          "xid": "DS_7845792",
                          "name": "http",
                          "enabled": false,
                          "modelType": "HTTP_RECEIVER",
                          "validationMessages": [],
                          "setPointUrl": "",
                          "ipWhiteList": [
                            "*.*.*.*"
                          ],
                          "deviceIdWhiteList": [
                            "*"
                          ],
                          "editPermission": "",
                          "purgeSettings": {
                            "override": false,
                            "frequency": {
                              "periods": 1,
                              "type": "YEARS"
                            }
                          },
                          "alarmLevels": {
                            "SET_POINT_FAILURE": "URGENT"
                          }
                        }
                    
                    H 1 Reply Last reply Reply Quote 0
                    • H
                      hrivers @phildunlap
                      last edited by

                      I fixed it-- the issue was that $devices needed to be json_encode()'ed when being sent via CURLOPT_POSTFIELDS (as well as Content-Type: application/json)

                      1 Reply Last reply Reply Quote 0
                      • phildunlapP
                        phildunlap
                        last edited by

                        Glad to hear it, thanks for sharing the resolution!

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post