merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

merchant_api_get_product_image.c (5194B)


      1 /*
      2   This file is part of TALER
      3  Copyright (C) 2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Lesser General Public License as published by the Free Software
      7   Foundation; either version 2.1, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
     12 
     13   You should have received a copy of the GNU Lesser General Public License along with
     14   TALER; see the file COPYING.LGPL.  If not, see
     15   <http://www.gnu.org/licenses/>
     16 */
     17 /**
     18  * @file merchant_api_get_product_image.c
     19  * @brief Implementation of the GET /products/$HASH/image request
     20  * @author Bohdan Potuzhnyi
     21  */
     22 #include "platform.h"
     23 #include <curl/curl.h>
     24 #include <jansson.h>
     25 #include <microhttpd.h>
     26 #include <gnunet/gnunet_util_lib.h>
     27 #include <gnunet/gnunet_curl_lib.h>
     28 #include <taler/taler_error_codes.h>
     29 #include <taler/taler_json_lib.h>
     30 #include "taler_merchant_service.h"
     31 #include "merchant_api_curl_defaults.h"
     32 
     33 
     34 /**
     35  * Handle for a GET /products/$HASH/image operation.
     36  */
     37 struct TALER_MERCHANT_ProductImageGetHandle
     38 {
     39   /**
     40    * The url for this request.
     41    */
     42   char *url;
     43 
     44   /**
     45    * Handle for the request.
     46    */
     47   struct GNUNET_CURL_Job *job;
     48 
     49   /**
     50    * Function to call with the result.
     51    */
     52   TALER_MERCHANT_ProductImageGetCallback cb;
     53 
     54   /**
     55    * Closure for @a cb.
     56    */
     57   void *cb_cls;
     58 
     59   /**
     60    * Reference to the execution context.
     61    */
     62   struct GNUNET_CURL_Context *ctx;
     63 };
     64 
     65 
     66 /**
     67  * Function called when we're done processing the
     68  * HTTP GET /products/$HASH/image request.
     69  *
     70  * @param cls the `struct TALER_MERCHANT_ProductImageGetHandle`
     71  * @param response_code HTTP response code, 0 on error
     72  * @param response response body, NULL if not in JSON
     73  */
     74 static void
     75 handle_get_product_image_finished (void *cls,
     76                                    long response_code,
     77                                    const void *response)
     78 {
     79   struct TALER_MERCHANT_ProductImageGetHandle *pigh = cls;
     80   const json_t *json = response;
     81   struct TALER_MERCHANT_ProductImageGetResponse pir = {
     82     .hr.http_status = (unsigned int) response_code,
     83     .hr.reply = json
     84   };
     85 
     86   pigh->job = NULL;
     87   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     88               "Got /products/$HASH/image response with status code %u\n",
     89               (unsigned int) response_code);
     90   switch (response_code)
     91   {
     92   case MHD_HTTP_OK:
     93     {
     94       struct GNUNET_JSON_Specification spec[] = {
     95         GNUNET_JSON_spec_string ("image",
     96                                  &pir.details.ok.image),
     97         GNUNET_JSON_spec_end ()
     98       };
     99 
    100       if (GNUNET_OK ==
    101           GNUNET_JSON_parse (json,
    102                              spec,
    103                              NULL, NULL))
    104       {
    105         pigh->cb (pigh->cb_cls,
    106                   &pir);
    107         GNUNET_JSON_parse_free (spec);
    108         TALER_MERCHANT_product_image_get_cancel (pigh);
    109         return;
    110       }
    111       pir.hr.http_status = 0;
    112       pir.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    113       break;
    114     }
    115   case MHD_HTTP_NOT_FOUND:
    116   case MHD_HTTP_BAD_REQUEST:
    117     pir.hr.ec = TALER_JSON_get_error_code (json);
    118     pir.hr.hint = TALER_JSON_get_error_hint (json);
    119     break;
    120   default:
    121     pir.hr.ec = TALER_JSON_get_error_code (json);
    122     pir.hr.hint = TALER_JSON_get_error_hint (json);
    123     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    124                 "Unexpected response code %u/%d\n",
    125                 (unsigned int) response_code,
    126                 (int) pir.hr.ec);
    127     break;
    128   }
    129   pigh->cb (pigh->cb_cls,
    130             &pir);
    131   TALER_MERCHANT_product_image_get_cancel (pigh);
    132 }
    133 
    134 
    135 struct TALER_MERCHANT_ProductImageGetHandle *
    136 TALER_MERCHANT_product_image_get (
    137   struct GNUNET_CURL_Context *ctx,
    138   const char *backend_url,
    139   const char *image_hash,
    140   TALER_MERCHANT_ProductImageGetCallback cb,
    141   void *cb_cls)
    142 {
    143   struct TALER_MERCHANT_ProductImageGetHandle *pigh;
    144   CURL *eh;
    145 
    146   pigh = GNUNET_new (struct TALER_MERCHANT_ProductImageGetHandle);
    147   pigh->ctx = ctx;
    148   pigh->cb = cb;
    149   pigh->cb_cls = cb_cls;
    150   {
    151     char *path;
    152 
    153     GNUNET_asprintf (&path,
    154                      "products/%s/image",
    155                      image_hash);
    156     pigh->url = TALER_url_join (backend_url,
    157                                 path,
    158                                 NULL);
    159     GNUNET_free (path);
    160   }
    161   if (NULL == pigh->url)
    162   {
    163     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    164                 "Could not construct request URL.\n");
    165     GNUNET_free (pigh);
    166     return NULL;
    167   }
    168   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    169               "Requesting URL '%s'\n",
    170               pigh->url);
    171   eh = TALER_MERCHANT_curl_easy_get_ (pigh->url);
    172   pigh->job = GNUNET_CURL_job_add (ctx,
    173                                    eh,
    174                                    &handle_get_product_image_finished,
    175                                    pigh);
    176   return pigh;
    177 }
    178 
    179 
    180 void
    181 TALER_MERCHANT_product_image_get_cancel (
    182   struct TALER_MERCHANT_ProductImageGetHandle *pigh)
    183 {
    184   if (NULL != pigh->job)
    185     GNUNET_CURL_job_cancel (pigh->job);
    186   GNUNET_free (pigh->url);
    187   GNUNET_free (pigh);
    188 }