Appengine wildcard URL issues - google-app-engine

I have a page in my Google appengine that needs to take records from the datastore based on parameters fed through the URL of the page. The URL of the page looks like http://example.appspot.com/page/WILDCARD/, where WILDCARD is a unique identifier (32-character hex string) for a record. It then takes the record specified by WILDCARD and displays it on the template page.html, or at least that's what it's supposed to do. Whenever I access the page as http://example.appspot.com/page/WILDCARD/, I get a 404 error. Does anyone know why/can anyone suggest reasons for why this might be? Thanks.
In my WSGI class handlers, I have
('/page/([^/]+)/', PageHandler),
and the PageHandler class itself is
class PageHandler(webapp2.RequestHandler):
def get(self, recordID):
allrecords = db.GqlQuery("SELECT RECORD FROM RECORDS WHERE recordid = :record",record = recordID)
if not allrecords:
self.redirect("../") #the URL is screwed up, so we're redirecting you back to the main page
else:
for row in allrecords:
template = JINJA.get_template("page.html")
self.response.out.write(template.render({ "recordtext":row.RECORD, "recordid":recordID }))
Additional details: JINJA is just the default jinja environment, I'm pretty sure there's nothing wrong with that. RECORDS is a db.Model type class that has members RECORD, a text property and recordid, a string property. It's currently not populated with any data.
EDIT: Nevermind, I solved the problem. It was my own stupidity when I simplified the problem down. It turns out that in actual implementation (i.e. the complicated version of this example), I had a tiny discrepancy between what I thought my URL was and what it actually was for /page/. Apologies.

Try
webapp2.Route('/page/<recordID>/', handler=PageHandler)
for your route definition.
You can insert it along your other route tuples like:
app = webapp2.WSGIApplication([
('/', Homepage),
webapp2.Route('/page/<recordID>/', handler=PageHandler),
('/otherpage', SomeOtherPage)
])
What you have might work fine as well with proper regex but I find it easier to read code when using template URLs defining expected paths and naming them.
See more: https://webapp-improved.appspot.com/guide/routing.html

Nevermind, I solved the problem. It was my own stupidity when I simplified the problem down. It turns out that in actual implementation (i.e. the complicated version of this example), I had a tiny discrepancy between what I thought my URL was and what it actually was for /page/. Apologies.

This what work for me:
app = webapp2.WSGIApplication([
('/', Homepage),
('/page/.*', PageHandler),
('/otherpage', SomeOtherPage)
])

Related

Getting $http.put() to send correctly formatted data, instead of JSON object

So, I spent some time and built a quick API for a project that I'm doing for myself.
I used the Postman add-on for Chrome to mimic PUT and DELETE quests to make sure everything worked correctly. Really happy I did that, as I learned a lot about PHP's shortcomings with PUT and DELETE requests.
Using the API I've had working with Postman, I started moving everything over to AngularJs controllers and such.
I'm trying to get a user to claim a row in a database as the login information for the users is different than this particular information. I couldn't figure out why the put requests to claim the row in my database wasn't working. Lo and behold, the data being parsed from my parsestr(file_get_contents('php://input')) had 1 array key, which was a JSON string.
I've looked, and I can't seem to find a solid answer either through Stackoverflow or Google (maybe I missed it somewhere in the config options), So my question is this: is there any way I can get the $http.put call send the data to the server correctly?
Thanks to user Chandermani for pointing me to the link at this URL which answered the base of my question.
From the above link, I found myself on This Blog post submitted by another user. In the end, what I ended up doing was the following:
taking param() function from the above link, as well as implementing these lines of code:
var app = angular.module('ucpData', [] , function($httpProvider){
$httpProvider.defaults.transformRequest = [function(data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
});
Is how I worked around the problem. For some developers, you may actually want to keep the default transformRequest settings, but for the project I am doing I know that I will end up forgetting to call param() at some point, and my server doesn't naturally accept json data anyway. I would caution future developers to consider what they are attempting to do before they alter the transformRequest array directly.

Redirect given a certain url

I'm writing a url shortener, I already solve url shortening. Given a certain long URL (LURL), I get a CODE with the help of a script and a database to form a short URL (SURL) of the type:
mysite.com/CODE
So the ralationship between the code and the LURL is stored and must be consulted in the DB. Now as you can see I need a way to do that. My plan is that all the all url in mysite.com direct to the same page where the CODE is taken as a parameter and in this way make a consult in the db fetching the code from the SURL and then redirect with a script to the LURL.
I dont want to generate a SURL that uses a GET request like:
mysite.com/?CODE
It would be easier but I decided not to do it because it defeats the propose of url shorteners by occupying a character unnecessarily.
How would you implement it? Is this method convenient? If you do not think so I would really appreciate you give me your opinion. Maybe there are better ways to do it now that I already have the DB and the shortening algorithm. See you later.
http://www.webcheatsheet.com/PHP/get_current_page_url.php
check out the curPageURL() function.
$pageURL = curPageURL();
$itemArray= explode("/", $pageURL);
$myCode = $itemArray[1];
something like that will do, but not tested. It just gives you an idea of what you can do.
also, to get the url, here is an simplified version: http://phpeasystep.com/phptu/27.html

CakePHP, extensions and layouts

I have a controller method that has long been handling JSON requests by parsing that extension, but now I need to open it up to cross domain ajax so I'd like to offer a JSONP variant by parsing that extension as well. I've already updated my routes.php file:
Router::parseExtensions( 'json', 'jsonp' );
So far all is well, but the happiness ends when the results are rendered. While the .json extension automagically picks up the json/default.ctp layout, the .jsonp content continues to adopt the non-specific default layout (and all of its unnecessary HTML content). I've tried using RequestHandler::setContent() to set the response content type to both json and js, but that doesn't seem to be what triggers the call to a given layout directory.
Does anyone know what does determine which content-specific layout directory is called? I tried creating jsonp/default.ctp and I've tried creating a js/default.ctp layout with my JSONP result, but nothing seems to engage. I just get the normal default.
Any insight into how extensions/content type are mapped to these layout directories would be much appreciated.
I've temporarily solved this by explicitly setting the layoutPath value:
$this->layoutPath = $params['url']['ext'];
This feels like one of those things where there must be a better solution, but maybe this is it. I'm going to leave the question open for a bit in the hopes that someone else has a solution that involves Cake's automagic.

CakePHP Routing Alias, no prefix

I have a dashboard with a series of widgets. Per specification, the widgets need to be buried under a /widgets/ directory.
So I have added the following to my routes.php
Router::connect('/widget/:controller/:action/*', array());
But I seem to be running into trouble on widget/links/ and widget/links/view/1
I am new to CakePHP, but this doesn't seem all that impressive. I have yet to find anything in the Book or by search. So any help is appreciated.
Thanks.
Well...at the risk of stating the obvious...your route starts with /widget/, but you indicate that you're trying to access it via a plural URI (/widgets/). That's a problem. If that's just a typo, it would help to know what error you're seeing when you "run into trouble".
UPDATE:
Yes that was a typo. I corrected it. The error that appears for widget/links/ is: Error: WidgetController could not be found. It appears my index/default route is the main problem.
Given that information, it appears that CakePHP thinks that widget is your controller. Cake processes routes top down and finds the first one that matches. Ensure that you don't have a route above this one that looks something like /:controller/... or any other route above this one that starts with a variable.

Dealing with Alias URLs in CakePHP

I am rewriting our company website in cakephp, and need to find a way to do the following:
A user enters our site by using one
of the promotional alias URLS that
has been pregenerated for a specific
media advert ( magazine, web
promotion etc )
The URL is checked against a
database of alias URLs, and if an
alias exists, then a specific
tracking code is written into the
session.
I have considered several options, none of which seem suitable for this purpose. They are:
Putting the lookup script in the
beforeFilter() in appcontroller, so
that its included in every
controller. (Writes a session value
so it only perfoms once.)
This option only works for existing contollers, and gives the
Cake 'missing controller' error if a
URL doesn't exist.
Specific routes for each alias in
Routes.php - Works but there are
potentially hundreds of alias urls
added/removed regularly via admin
interface.
Route all site URLs to their own
actions, and having an 'everything
else' rule, for the alias URLs that
maps to my lookup script. - Messy
and I lose the built in Cake
routing.
Custom 404. - I don't want to
return 404's for these urls, as I
feel its bad practice unless they
really don't map to anything.
I really could do with a place in the application flow where I can put this lookup/tracking script, and I'm fairly new to cake so I'm stumped.
EDIT: Also, I know that a subfolder called say 'promo' would easily do this, but I have a lot of legacy URLS from our old site, that need handling too.
Note: I'm making an assumption that your promo URLs are in the form of "domain.com/advert-259" or something like that (i.e. no "domain.com/adverts/advert-259'). That would be just too simple :)
Hopefully, you can use the routing with some regex. Add this to your /config/routes.php and let me know if a different regex will help :)
$controllers = Configure::listObjects('controller');
foreach ($controllers as &$value)
{
$value = Inflector::underscore($value);
}
Router::connect('/:promo', array('controller' => 'promos', 'action' => 'process'), array('promo' => '(?!('.implode('|', $controllers).')\W+)[a-zA-Z\-_]+/?$'));
Now you can handle all your promo codes in PromosController::process().
Basically, it checks for a promo code in url, excluding those in the $controllers array (i.e. your regular routes won't be messed up).
Later on you might want to consider caching the value of Configure::listObjects() depending on the speed of your app and your requirements.
A very interesting question. I think I would use item #3. It's not really that messy -- after all, this typically is handled by the pages controller in my stuff. That's how I'd handle it - hardcode your routes to your controllers in routes.php, then have a matchall route that will work for your promo codes. This allows you to keep legacy URLs, as well as use a lot of the standard cake stuff (you probably will just have to explicitly state each of your controllers routes, not such a chore...) Additionally, it will let you do some cool stuff with 404 errors -- you can put some logic in there to try and figure out where they were trying to go, so you can superpower your 404's.

Resources