Magento rest api getting error Request does not match any route - rest

I have created a rest api web service but I am getting error on hitting the url
http://localhost:81/magento/api/rest/category/2
<magento_api>
<messages>
<error>
<data_item>
<code>404</code>
<message>Request does not match any route.</message>
</data_item>
</error>
</messages>
</magento_api>
My api2.xml is:-
<?xml version="1.0"?>
<config>
<api2>
<resource_groups>
<esoft_rescategories translate="title" module="Esoft_Restcategories">
<title>Esoft Restcategories API</title>
<sort_order>11</sort_order>
</esoft_rescategories>
</resource_groups>
<resources>
<esoft_restcategories translate="title" module="Esoft_Restcategories">
<group>esoft_rescategories</group>
<model>esoft_restcategories/api2_restapi</model>
<title>Categories</title>
<sort_order>11</sort_order>
<privileges>
<admin>
<create>1</create>
<!--<retrieve>1</retrieve>
<update>1</update>
<delete>1</delete>-->
</admin>
<guest>
<retrieve>1</retrieve>
<!--<create>1</create>
<update>1</update>
<delete>1</delete>-->
</guest>
</privileges>
<attributes>
<category_id>Category ID</category_id>
<name>Name</name>
<parent_id>Category Parent ID</parent_id>
<child_id>Category Child List</child_id>
<active>Active</active>
<level>Level</level>
<position>Position</position>
</attributes>
<routes>
<route_entity>
<route>/categories/:cat_id</route>
<action_type>entity</action_type>
</route_entity>
<route_collection>
<route>/categories</route>
<action_type>collection</action_type>
</route_collection>
</routes>
<versions>1</versions>
</esoft_restcategories>
</resources>
</api2>
</config>
My version file for guest is:-
<?php
class Esoft_Restcategories_Model_Api2_Restapi_Rest_Guest_V1 extends Esoft_Restapi_Model_Api2_Restapi {
/**
* Retrieve list of category list.
*
* #return array
*/
protected function _retrieveCollection()
{
$ruleId = $this->getRequest()->getParam('cat_id');
// $cat_mod = Mage::getModel('catalog/category')->load($ruleId)->toArray();
$cats = Mage::getModel('catalog/category')->load($ruleId);
$subcats = Mage::getModel('catalog/category')->load($ruleId)->getChildren();
$cur_category = array();
$node['category_id'] = $ruleId;
$node['name'] = $cats->getName();
$node['parent_id'] = $cats->getParentId();
$node['child_id'] = $subcats;
if($cats->getIsActive()){
$node['active'] = 1;
}else{
$node['active'] = 0;
}
$node['level'] = $cats->getLevel();
$node['position'] = $cats->getPosition();
$cur_category[] = $node;
// $subcats = Mage::getModel('catalog/category')->load($ruleId)->getAllChildren();
// $subcats = Mage::getModel('catalog/category')->load($ruleId)->getChildren();
if($subcats != '')
{
foreach(explode(',',$subcats) as $subCatid)
{
$_category = Mage::getModel('catalog/category')->load($subCatid);
$childcats = Mage::getModel('catalog/category')->load($subCatid)->getChildren();
$node['category_id'] = $subCatid;
$node['name'] = $_category->getName();
$node['parent_id'] = $_category->getParentId();
$node['child_id'] = $childcats;
if($_category->getIsActive()){
$node['active'] = 1;
}else{
$node['active'] = 0;
}
$node['level'] = $_category->getLevel();
$node['position'] = $_category->getPosition();
$cur_category[] = $node;
}
}
return $cur_category;
}
}
Please let me know how to fix this error.
Also let me know on what basis we define routes.

Simple answer for those searching for cause of this error:
Request does not match any route
Is that you are posting the wrong METHOD such as GET/POST/PUT/DELETE.
It could also be the path of the API url itself is wrong.

As per your description your url format is wrong (route miss matching in given url).
<route>/categories/:cat_id</route>
^^^^^^^^^
So you need to change the url like below
http://localhost:81/magento/api/rest/categories/2

Related

Custom sitemap handler causing site to fail to load (Sitecore)

I'm trying to add a custom handler to my site to redirect to the appropriate Sitemap for the current language, i.e. mysite.com/sitemap.xml --> sitemap-en.xml, mysite.es/sitemap.xml --> sitemap-es.xml, etc.
This is my setup:
handler trigger patch:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<customHandlers>
<handler trigger="sitemap.xml" handler="sitemap.ashx" />
</customHandlers>
</sitecore>
</configuration>
web.config:
<add path="sitemap.ashx" verb="*" type="MySite.CustomSitecore.Handlers.SitemapHandler,MySite" name="SitemapXml" />
handler:
namespace MySite.CustomSitecore.Handlers
{
public class SitemapHandler : IHttpHandler
{
public bool IsReusable
{
get
{
throw new NotImplementedException();
}
}
public void ProcessRequest(HttpContext context)
{
try
{
var curSite = Sitecore.Context.Site;
var m_Sites = SitemapManagerConfiguration.GetSites();
foreach (DictionaryEntry site in m_Sites)
{
if (site.Key.ToString().Equals(curSite.Name))
{
var filepath = site.Value;
HttpContext.Current.Response.Redirect("/" + filepath, false);
return;
}
}
return;
}
catch (Exception ex)
{
Log.Info("Error in SitemapHandler: " + ex, this);
}
}
}
}
It's not working though, when I try to go to mysite.com/sitemap.xml and debug it steps through the redirect process as expected and looks as if it should be successfully redirecting to /sitemap-en.xml, but the page just spins and displays browser error saying that the page can't be loaded.
I have tried a couple different redirect methods, but nothing has worked. I tried this as well:
HttpContext.Current.Response.StatusCode = 200;
HttpContext.Current.Response.ContentType = "text/xml";
HttpContext.Current.Response.AddHeader("Location", "/" + filepath);
HttpContext.Current.Response.End();
return;
Not sure if this is the issue, But out of the box Sitecore don't allow .xml files. Security hardening.
You can use somethings like this in the config, to add the .xml extension
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<preprocessRequest help="Processors should derive from Sitecore.Pipelines.PreprocessRequest.PreprocessRequestProcessor">
<processor type="Sitecore.Pipelines.PreprocessRequest.FilterUrlExtensions, Sitecore.Kernel">
<param desc="Allowed extensions (comma separated)">aspx, ashx, asmx, xml</param>
</processor>
</preprocessRequest>
</pipelines>
</sitecore>
</configuration>
But I think a better solution, use the default and take security seriously.
Tell the search engine what the url of the sitemap is by using a robots.txt
User-agent: *
Sitemap: /sitemap.ashx

Bing ads - Upload offline conversion

I am trying to upload my offline conversions to bing ads through API. I am using below code. And for now I am using sandbox account to test it.
val authorizationData = AuthorizationData().apply {
developerToken = "BBD37VB98"
authentication = PasswordAuthentication("xyz", "xyz")
customerId = 0
accountId = 0
}
var bulkOfflineConversion = BulkOfflineConversion().apply {
clientId = "xyz"
offlineConversion = OfflineConversion().apply {
conversionCurrencyCode = "USD"
conversionName = "phone_sales"
conversionTime = Calendar.getInstance()
conversionValue = 10.00
microsoftClickId = "f894f652ea334e739002f7167ab8f8e3"
}
}
val uploadEntities = ArrayList<BulkEntity>()
uploadEntities.add(bulkOfflineConversion)
var entityUploadParameters = EntityUploadParameters().apply {
entities = uploadEntities
responseMode = ResponseMode.ERRORS_AND_RESULTS
resultFileDirectory = File("/tmp/")
resultFileName = "bing.csv"
overwriteResultFile = true
}
//BulkServiceManager(authorizationData).
var task = BulkServiceManager(authorizationData).uploadEntitiesAsync(entityUploadParameters, null).get()
val resultEntities = ArrayList<BulkEntity>()
task.forEach {
resultEntities.add(it)
}
task.close()
After executing above code I got following XML response
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:TrackingId xmlns:h="https://bingads.microsoft.com/CampaignManagement/v11">b0e0e060-70fd-4bc2-9f40-b1ebcf38adb6</h:TrackingId>
</s:Header>
<s:Body>
<GetBulkUploadStatusResponse xmlns="https://bingads.microsoft.com/CampaignManagement/v11">
<Errors xmlns:i="http://www.w3.org/2001/XMLSchema-instance" i:nil="true" />
<ForwardCompatibilityMap xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<PercentComplete>100</PercentComplete>
<RequestStatus>Completed</RequestStatus> <ResultFileUrl>https://bingadsappsstoragesi.blob.core.windows.net/bulkuploadresultfiles/6883bbd6-cdd5-4f1b-b1cf-65995601afd0.zip?sv=2015-12-11&sr=b&sig=%2B74DyfhzKeamKIMLIrHLyH93rwU3WNk6necXpULCrDk%3D&st=2018-04-30T05%3A43%3A16Z&se=2018-04-30T06%3A08%3A16Z&sp=rl</ResultFileUrl>
</GetBulkUploadStatusResponse>
</s:Body>
</s:Envelope>`
But When I logged into my account, I don't see any record. Can somebody help me in uploading my offline records.
Am I missing out something here. Do I need to configure anything else in my sandbox account?
Suggestions have been proposed in the Bing Ads API Development Forum and I confirmed that sandbox will not record the offline conversion data. I hope this helps!

How to write Monolog logs into a file AND remote database

I have a Symfony2 -project and it writes the logs into different files beautifully, but I would like it to write the logs into a remote database(mongodb) as well. I would like to keep the actual log files in the servers as a backup in case something goes wrong with the database connection.
Question 1:
Is it even possible to save the same logs into two different places at the same time?
Question 2:
How do I save the logs into the mongodb? I don't necessarily need specific mongodb-instructions, but some guidelines on how to write into a remote db with monologger. The mongodb-specific instructions are also welcome if available. ;)
Question 3(OPTIONAL):
Can I get a full error stack into the logs somehow? Where could one find a full list of what data the Monolog can actually write and how to write?
There was a very good Blogpost sometime back for logging to a mysql database with monolog and doctrine. I can't find it anymore so i will just add the neccessary Files here and you can adjust it.
The whole logic is done in the DatabaseHandler so you can just change from
mysql inserts to a handling for your mongodb.
This code is not mine if anyone knows the original post please comment.
BacktraceLoggerListener.php
namespace UtilsBundle\EventListener;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class BacktraceLoggerListener{
private $_logger;
public function __construct(LoggerInterface $logger = null)
{
$this->_logger = $logger;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$this->_logger->addError($event->getException());
}
}
DatabaseHandler.php
namespace UtilsBundle\Logger;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;
/**
* Stores to database
*
*/
class DatabaseHandler extends AbstractProcessingHandler{
protected $_container;
/**
* #param string $stream
* #param integer $level The minimum logging level at which this handler will be triggered
* #param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
parent::__construct($level, $bubble);
}
/**
*
* #param type $container
*/
public function setContainer($container)
{
$this->_container = $container;
}
/**
* {#inheritdoc}
*/
protected function write(array $record)
{
// Ensure the doctrine channel is ignored (unless its greater than a warning error), otherwise you will create an infinite loop, as doctrine like to log.. a lot..
if( 'doctrine' == $record['channel'] ) {
if( (int)$record['level'] >= Logger::WARNING ) {
error_log($record['message']);
}
return;
}
// Only log errors greater than a warning
// TODO - you could ideally add this into configuration variable
if( (int)$record['level'] >= Logger::NOTICE ) {
try
{
// Logs are inserted as separate SQL statements, separate to the current transactions that may exist within the entity manager.
$em = $this->_container->get('doctrine')->getManager();
$conn = $em->getConnection();
$created = date('Y-m-d H:i:s');
$serverData = ""; //$record['extra']['server_data'];
$referer = "";
if (isset($_SERVER['HTTP_REFERER'])){
$referer= $_SERVER['HTTP_REFERER'];
}
$stmt = $em->getConnection()->prepare('INSERT INTO system_log(log, level, server_data, modified, created)
VALUES(' . $conn->quote($record['message']) . ', \'' . $record['level'] . '\', ' . $conn->quote($referer) . ', \'' . $created . '\', \'' . $created . '\');');
$stmt->execute();
} catch( \Exception $e ) {
// Fallback to just writing to php error logs if something really bad happens
error_log($record['message']);
error_log($e->getMessage());
}
}
}
}
We used xml here but this can be done in
services.yml too
services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="utils.database.logger" class="UtilsBundle\Logger\DatabaseHandler">
<call method="setContainer">
<argument type="service" id="service_container" />
</call>
</service>
<service id="utils.backtrace.logger.listener" class="UtilsBundle\EventListener\BacktraceLoggerListener">
<argument type="service" id="logger" />
<tag name="monolog.logger" channel="backtrace" />
<tag name="kernel.event_listener" event="kernel.exception" method="onKernelException" />
</service>
</services>
And lastly add the handler to your monolog config in
config_**.yml so here for production for example
config_prod.yml
monolog:
handlers:
main:
type: rotating_file
action_level: error
max_files: 10
handler: nested
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
database:
type: service
level: notice
id: utils.database.logger
channels: ["!translation"]
Hope that helps
Hope I can some things up for you:
Question 1: Yes its possible. E.G. you can do smt. like:
$this->logger->pushHandler(new StreamHandler('/path/to/logs/123_info.log', Logger::INFO));
$this->logger->pushHandler(new StreamHandler('/path/to/logs/456_warning.log', Logger::INFO));
So if $this->logger->addInfo("testinfo"); this is getting logged in both streams.
Question 2: There is a MongoDBHandler as according to the StreamHandler. You should be able do configure it and pass it along to the pushHandler method or if you want to have it in your services look at MongoDBConfiguration.
Question 3:
This should help: Configure Monolog
Hope that helps.

Alfresco REST API:Data Size Limit?

I am developing REST based webservices in alfresco for data transfer & want to know what is the maximum amount of data i can send/get thru REST protocol?
Any reference would be very helpful.
Regards.
The max amount of data is as large as 2147000000. That's why if your data is large enough it is advisable to stream it to post to your REST service. Here's an example.
Sender/ Uploader Application or Client
var sb = new StringBuilder();
sb.Append("Just test data. You can send large one also");
var postData = sb.ToString();
var url = "REST Post method example http://localhost:2520/DataServices/TestPost";
var memoryStream = new MemoryStream();
var dataContractSerializer = new DataContractSerializer(typeof(string));
dataContractSerializer.WriteObject(memoryStream, postData);
var xmlData = Encoding.UTF8.GetString(memoryStream.ToArray(), 0, (int)memoryStream.Length);
var client = new WebClient();
client.UploadStringAsync(new Uri(url), "POST", "");
client.Headers["Content-Type"] = "text/xml";
client.UploadStringCompleted += (s, ea) =>
{
if (ea.Error != null) Console.WriteLine("An error has occured while processing your request");
var doc = XDocument.Parse(ea.Result);
if (doc.Root != null) Console.WriteLine(doc.Root.Value);
if (doc.Root != null && doc.Root.Value.Contains("1"))
{
string test = "test";
}
};
REST Service method
[WebInvoke(UriTemplate = "TestPost", Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Xml)]
public string Publish(string market,string sportId, Stream streamdata)
{
var reader = new StreamReader(streamdata);
var res = reader.ReadToEnd();
reader.Close();
reader.Dispose();
}
Don't forget to put the following configuration settings on your REST Service config file if you don't have this it will throw you an error
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime maxRequestLength="2147000000" maxQueryStringLength="2097151" maxUrlLength="2097151"/>
</system.web>
<system.webServer>
........
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" maxReceivedMessageSize="2147000000" maxBufferPoolSize="2147000000" maxBufferSize="2147000000"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>

Working with authorized .net payment gateway in ios

i am working with authorized .net payement gateway in ios
In the following method
(void) createTransaction {
AuthNet *an = [AuthNet getInstance];
[an setDelegate:self];
CreditCardType *creditCardType = [CreditCardType creditCardType];
creditCardType.cardNumber = #"4111111111111111";
NSLog(#"babul cardNumber is %#",creditCardType.cardNumber);
creditCardType.cardCode = #"100";
NSLog(#"babul cardCode is %#",creditCardType.cardCode);
creditCardType.expirationDate = #"1212";
NSLog(#"babul expirationDate is %#",creditCardType.expirationDate);
PaymentType *paymentType = [PaymentType paymentType];
paymentType.creditCard = creditCardType;
ExtendedAmountType *extendedAmountTypeTax = [ExtendedAmountType extendedAmountType];
extendedAmountTypeTax.amount = #"0";
extendedAmountTypeTax.name = #"Tax";
ExtendedAmountType *extendedAmountTypeShipping = [ExtendedAmountType extendedAmountType];
extendedAmountTypeShipping.amount = #"0";
extendedAmountTypeShipping.name = #"Shipping";
LineItemType *lineItem = [LineItemType lineItem];
lineItem.itemName = #"Soda";
lineItem.itemDescription = #"Soda";
lineItem.itemQuantity = #"1";
lineItem.itemPrice = #"1.00";
lineItem.itemID = #"1";
TransactionRequestType *requestType = [TransactionRequestType transactionRequest];
requestType.lineItems = [NSArray arrayWithObject:lineItem];
requestType.amount = #"1.00";
requestType.payment = paymentType;
requestType.tax = extendedAmountTypeTax;
requestType.shipping = extendedAmountTypeShipping;
CreateTransactionRequest *request = [CreateTransactionRequest createTransactionRequest];
request.transactionRequest = requestType;
request.transactionType = AUTH_ONLY;
request.anetApiRequest.merchantAuthentication.mobileDeviceId =
[[[UIDevice currentDevice] uniqueGlobalDeviceIdentifier]
stringByReplacingOccurrencesOfString:#"-" withString:#"_"];
request.anetApiRequest.merchantAuthentication.sessionToken = sessionToken;
[an purchaseWithRequest:request];
}
i am getting the response as
Create Transaction response
2012-07-26 19:14:00.131 Authorized[2355:207] ErrorE00003The element 'merchantAuthentication' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 'mobileDeviceId' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'. List of possible elements expected: 'name, transactionKey, sessionToken, password' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.
namespace warning : xmlns: URI AnetApi/xml/v1/schema/AnetApiSchema.xsd is not absolute
ttp://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"
^
2012-07-26 19:14:00.131 Authorized[2355:207] Error = (null)
2012-07-26 19:14:00.247 Authorized[2355:207] babul output is Message.code = E00003
Message.text = The element 'merchantAuthentication' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 'mobileDeviceId' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'. List of possible elements expected: 'name, transactionKey, sessionToken, password' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.
Is there any alternative to the above problem and how the transactions are going to be stored in authorized .net
(i created my test account, i am giving those credentials, i approved my device but later i am getting the above error)
Thanks in advance
I think you need to go for in app purchase because Apple will not approve application payment through any web service or API.