Question

Does anyone have an idea about how to get a product with slash through the rest api ?

I have a product with sku 100/1. The closest I have gotten is to call:

get /rest/V1/products/100%252f1

But it returns {"message":"Requested product doesn't exist"}

Any idea ?

/Thomas

Was it helpful?

Solution

I was hoping there where a well known workaround for this, but for now I solved it by writing plugins.

To get and put product, I plugged in before the get and save function in \Magento\Catalog\Api\ProductRepositoryInterface

<?php

namespace Vendor\Module\Plugin\Product;

class RestSkuFix
{
    /**
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param string $sku
     * @param bool $editMode
     * @param int|null $storeId
     * @param bool $forceReload
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @return array
     */
    public function beforeGet($productRepository, $sku, $editMode = false, $storeId = null, $forceReload = false)
    {
        $sku = urldecode($sku);
        return [$sku, $editMode, $storeId, $forceReload];
    }

    /**
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param \Magento\Catalog\Api\Data\ProductInterface $product
     * @param bool $saveOptions
     * @return array
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\StateException
     * @throws \Magento\Framework\Exception\CouldNotSaveException
     */
    public function beforeSave($productRepository, \Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
    {
        $product->setSku(urldecode($product->getSku()));
    }
}

And this I did only in rest webapi by registering the plugin in Vendor/Module/etc/webapi_rest/di.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Model\ProductRepository">
        <plugin name="ProductRepositoryRestSkuFix" type="\Vendor\Module\Plugin\Product\RestSkuFix" />
    </type>
</config>

Now I can get and put product with slash by

get /rest/V1/products/100%252f1

and

put /rest/V1/products/100%252f1

OTHER TIPS

Here is better workaround, no need to rewrite anything. Just create module containing only this webapi.xml file. Or just simply add to any existing module you have in project (even faster but not recommended).

<?xml version="1.0" ?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route url="/V1/{name-it-as-you-wish}" method="POST">
        <service class="Magento\Catalog\Api\ProductRepositoryInterface" method="get"/>
        <resources>
            <resource ref="Magento_Catalog::products" />
        </resources>
    </route>
</routes>

Now you can get product sending SKU via POST:

curl -g -X POST "$base_url/index.php/rest/V1/{name-it-as-you-wish}" \
-H "Authorization: Bearer $token" \
-H "Content-Type:application/json" \
-d '{"sku":"YOUR/SLASHED/SKU"}'

There's currently no solution to this. The only workaround is to rename the sku.

To extend the answer by TNordkvist - there are additional APIs that require this correction.

<?xml version="1.0" ?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- ... -->
    <type name="Magento\CatalogInventory\Model\StockRegistry">
        <plugin name="ProductRepositoryRestSkuFix" type="SmithAndAssociates\Fixes\Plugin\Product\RestSkuFix" />
    </type>
</config>

And in the RestSkuFix.php:

<?php
namespace Vendor\Module\Plugin\Product;
class RestSkuFix
{

//...

/**
 * @param \Magento\CatalogInventory\Model\StockRegistry $stockRegistry
 * @param string $productSku
 * @param int $scopeId
 * @return \Magento\CatalogInventory\Api\Data\StockItemInterface
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 */
public function beforeGetStockItemBySku($stockRegistry, $productSku, $scopeId = null)
{
    $productSku = urldecode($productSku);
    return [$productSku, $scopeId];
}

/**
 * @param \Magento\CatalogInventory\Model\StockRegistry $stockRegistry
 * @param string $productSku
 * @param int $scopeId
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 * @return array
 */
public function beforeGetStockStatusBySku($stockRegistry, $productSku, $scopeId = null)
{
    $productSku = urldecode($productSku);
    return [$productSku, $scopeId];
}

/**
 * @param \Magento\CatalogInventory\Model\StockRegistry $stockRegistry
 * @param string $productSku
 * @param int $scopeId
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 * @return array
 */
public function beforeGetProductStockStatusBySku($stockRegistry, $productSku, $scopeId = null)
{
    $productSku = urldecode($productSku);
    return [$productSku, $scopeId];
}

/**
 * @param \Magento\CatalogInventory\Model\StockRegistry $stockRegistry
 * @param string $productSku
 * @param \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem
 * @throws \Magento\Framework\Exception\NoSuchEntityException
 * @return array
 */
public function beforeUpdateStockItemBySku($stockRegistry, $productSku, \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem)
{
    $productSku = urldecode($productSku);
    return [$productSku, $stockItem];
}
}

Apply AllowEncodedSlashes directive in Apache

go to http.conf (or any conf file in sites-available)

<VirtualHost *:80>
   ...
   AllowEncodedSlashes On
   ...
</VirtualHost>
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top