2

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

4

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
1

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

1

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];
}
}
1

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"}'
  • This is actually a great solution. It worked well for me and required little modification. – Corgalore Jul 19 '18 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.