The 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
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
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 MagentoCatalogApiProductRepositoryInterface
<?php
namespace VendorModulePluginProduct;
class RestSkuFix
{
/**
* @param MagentoCatalogApiProductRepositoryInterface $productRepository
* @param string $sku
* @param bool $editMode
* @param int|null $storeId
* @param bool $forceReload
* @throws MagentoFrameworkExceptionNoSuchEntityException
* @return array
*/
public function beforeGet($productRepository, $sku, $editMode = false, $storeId = null, $forceReload = false)
{
$sku = urldecode($sku);
return [$sku, $editMode, $storeId, $forceReload];
}
/**
* @param MagentoCatalogApiProductRepositoryInterface $productRepository
* @param MagentoCatalogApiDataProductInterface $product
* @param bool $saveOptions
* @return array
* @throws MagentoFrameworkExceptionInputException
* @throws MagentoFrameworkExceptionStateException
* @throws MagentoFrameworkExceptionCouldNotSaveException
*/
public function beforeSave($productRepository, MagentoCatalogApiDataProductInterface $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="MagentoCatalogModelProductRepository">
<plugin name="ProductRepositoryRestSkuFix" type="VendorModulePluginProductRestSkuFix" />
</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
Method 2
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="MagentoCatalogApiProductRepositoryInterface" 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"}'
Method 3
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="MagentoCatalogInventoryModelStockRegistry">
<plugin name="ProductRepositoryRestSkuFix" type="SmithAndAssociatesFixesPluginProductRestSkuFix" />
</type>
</config>
And in the RestSkuFix.php:
<?php
namespace VendorModulePluginProduct;
class RestSkuFix
{
//...
/**
* @param MagentoCatalogInventoryModelStockRegistry $stockRegistry
* @param string $productSku
* @param int $scopeId
* @return MagentoCatalogInventoryApiDataStockItemInterface
* @throws MagentoFrameworkExceptionNoSuchEntityException
*/
public function beforeGetStockItemBySku($stockRegistry, $productSku, $scopeId = null)
{
$productSku = urldecode($productSku);
return [$productSku, $scopeId];
}
/**
* @param MagentoCatalogInventoryModelStockRegistry $stockRegistry
* @param string $productSku
* @param int $scopeId
* @throws MagentoFrameworkExceptionNoSuchEntityException
* @return array
*/
public function beforeGetStockStatusBySku($stockRegistry, $productSku, $scopeId = null)
{
$productSku = urldecode($productSku);
return [$productSku, $scopeId];
}
/**
* @param MagentoCatalogInventoryModelStockRegistry $stockRegistry
* @param string $productSku
* @param int $scopeId
* @throws MagentoFrameworkExceptionNoSuchEntityException
* @return array
*/
public function beforeGetProductStockStatusBySku($stockRegistry, $productSku, $scopeId = null)
{
$productSku = urldecode($productSku);
return [$productSku, $scopeId];
}
/**
* @param MagentoCatalogInventoryModelStockRegistry $stockRegistry
* @param string $productSku
* @param MagentoCatalogInventoryApiDataStockItemInterface $stockItem
* @throws MagentoFrameworkExceptionNoSuchEntityException
* @return array
*/
public function beforeUpdateStockItemBySku($stockRegistry, $productSku, MagentoCatalogInventoryApiDataStockItemInterface $stockItem)
{
$productSku = urldecode($productSku);
return [$productSku, $stockItem];
}
}
Method 4
There’s currently no solution to this. The only workaround is to rename the sku.
Method 5
Apply AllowEncodedSlashes directive in Apache
go to http.conf
(or any conf file in sites-available)
<VirtualHost *:80>
...
AllowEncodedSlashes On
...
</VirtualHost>
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0