Feature - Implemented Allow visit_url() to follow redirects in Relay Script

Not sure if bug or feature, but it seems that visit_url() handles redirect requests differently in a relay override than a regular script.
Same code, 2 debug logs:
relay
Code:
Connecting to clan_dreadsylvania.php...

Requesting: http://www.kingdomofloathing.com/clan_dreadsylvania.php?action=forceloc&loc=7
2 request properties

Field: Cookie = [appserver=www8; PHPSESSID=kmud4rlk4vssfgfu1im5752o47]
Field: User-Agent = [KoLmafia v16.0]

Retrieving server reply...

Retrieved: http://www.kingdomofloathing.com/clan_dreadsylvania.php?action=forceloc&loc=7

11 header fields
Field: null = [HTTP/1.1 302 Found]
Field: Date = [Sun, 18 Aug 2013 03:05:58 GMT]
Field: Content-Length = [0]
Field: Expires = [Thu, 19 Nov 1981 08:52:00 GMT]
Field: Location = [adventure.php?snarfblat=340]
Field: Content-Type = [text/html; charset=UTF-8]
Field: Connection = [keep-alive]
Field: Server = [nginx/0.8.55]
Field: X-Powered-By = [PHP/5.3.3]
Field: Cache-Control = [no-store, no-cache, must-revalidate, post-check=0, pre-check=0]
Field: Pragma = [no-cache]

                     Function visit_url returned:

and regular script
Code:
Connecting to clan_dreadsylvania.php...

Requesting: http://www.kingdomofloathing.com/clan_dreadsylvania.php?action=forceloc&loc=7
2 request properties

Field: Cookie = [appserver=www8; PHPSESSID=kmud4rlk4vssfgfu1im5752o47]
Field: User-Agent = [KoLmafia v16.0]

Retrieving server reply...

Retrieved: http://www.kingdomofloathing.com/clan_dreadsylvania.php?action=forceloc&loc=7

11 header fields
Field: null = [HTTP/1.1 302 Found]
Field: Date = [Sun, 18 Aug 2013 03:09:52 GMT]
Field: Content-Length = [0]
Field: Expires = [Thu, 19 Nov 1981 08:52:00 GMT]
Field: Location = [adventure.php?snarfblat=340]
Field: Content-Type = [text/html; charset=UTF-8]
Field: Connection = [keep-alive]
Field: Server = [nginx/0.8.55]
Field: X-Powered-By = [PHP/5.3.3]
Field: Cache-Control = [no-store, no-cache, must-revalidate, post-check=0, pre-check=0]
Field: Pragma = [no-cache]

Connecting to adventure.php...

Requesting: http://www.kingdomofloathing.com/adventure.php?snarfblat=340
2 request properties

Field: Cookie = [appserver=www8; PHPSESSID=kmud4rlk4vssfgfu1im5752o47]
Field: User-Agent = [KoLmafia v16.0]

Retrieving server reply...

Retrieved: http://www.kingdomofloathing.com/adventure.php?snarfblat=340

11 header fields
Field: null = [HTTP/1.1 302 Found]
Field: Date = [Sun, 18 Aug 2013 03:09:52 GMT]
Field: Content-Length = [0]
Field: Expires = [Thu, 19 Nov 1981 08:52:00 GMT]
Field: Location = [choice.php?forceoption=0]
Field: Content-Type = [text/html; charset=UTF-8]
Field: Connection = [keep-alive]
Field: Server = [nginx/0.8.55]
Field: X-Powered-By = [PHP/5.3.3]
Field: Cache-Control = [no-store, no-cache, must-revalidate, post-check=0, pre-check=0]
Field: Pragma = [no-cache]

Connecting to choice.php...

Requesting: http://www.kingdomofloathing.com/choice.php?forceoption=0
2 request properties

Field: Cookie = [appserver=www8; PHPSESSID=kmud4rlk4vssfgfu1im5752o47]
Field: User-Agent = [KoLmafia v16.0]

Retrieving server reply...

Retrieved: http://www.kingdomofloathing.com/choice.php?forceoption=0

10 header fields
Field: null = [HTTP/1.1 200 OK]
Field: Date = [Sun, 18 Aug 2013 03:09:52 GMT]
Field: Content-Length = [4484]
Field: Expires = [Thu, 19 Nov 1981 08:52:00 GMT]
Field: Content-Type = [text/html; charset=UTF-8]
Field: Connection = [keep-alive]
Field: Server = [nginx/0.8.55]
Field: X-Powered-By = [PHP/5.3.3]
Field: Cache-Control = [no-store, no-cache, must-revalidate, post-check=0, pre-check=0]
Field: Pragma = [no-cache]

Retrieving server reply
ResponseText has 4484 characters.

Can these be morphed together or is there at least a work-around for getting this in a relay script?
 

Veracity

Developer
Staff member
KoLmafia intentionally does not follow redirects for RelayRequests. In GenericRequest.handleServerRedirect():

Code:
		if ( this instanceof RelayRequest )
		{
			return true;
		}
I think the idea is that everything after that pertains to automating requests, and if you have a RelayRequest, you let the browser - or the script - do the redirect if it chooses to do so. Here is how it sets up to follow the redirect:

Code:
			this.constructURLString( this.redirectLocation, this.redirectMethod.equals( "POST" ) );
			return false;
And then it will resubmit the request.

It would probably be reasonable to give a relay script access to this.redirectLocation and this.redirectMethod so you could do the equivalent. Seems a little funky for a relay script; what if you are redirecting to fight.php or choice.php or ... anything ... which might want to be handled by a different relay script?

The current code is not a bug. I'll recharacterize this as a Feature Request.
 
Last edited:

Bale

Minion
There have been discussions concerning this in the past. Once in a while a thread pops up reporting an indecipherable bug in a relay script, but it turns out that is because a redirect is not being followed. I made one of those threads myself. The solution was to call the correct url, skipping the redirect.
 
... what if you are redirecting to fight.php or choice.php or ... anything ... which might want to be handled by a different relay script?
If that page was being loaded to be displayed in the relay browser, then I could understand this being an issue. But the current script is asking for the information; presumably the script asking for the page would like to work with it, unadulterated. Other scripts should have nothing to do with this process.

Consider the task at hand: I want the relay override to visit a choice.php page (via a redirect through adventure.php) and then from there navigate the noncombat to a predetermined outcome. When all is said and done, none of the source material gathered through the visit_url()s will be displayed to the user.

So, if the current behavior is intentional (I'm trying to think of an instance where not following a redirect would actually be beneficial to the relay script ... could you highlight an example?) then I suppose this is a request indeed, for some sort of... visit_url2 or follow_url() or something.

If you like what clan_raidlog.ash does now, then you'll probably love it more should this become possible. ;)

There have been discussions concerning this in the past. Once in a while a thread pops up reporting an indecipherable bug in a relay script, but it turns out that is because a redirect is not being followed. I made one of those threads myself. The solution was to call the correct url, skipping the redirect.

I considered that, and I'm going to try a few more stabs at it now that rollover has passed, but if you look at the requests... I don't know that the skipping to the "correct" url is actually going to work. Note that my original request is "http://www.kingdomofloathing.com/clan_dreadsylvania.php?action=forceloc&loc=7" which redirects to "http://www.kingdomofloathing.com/adventure.php?snarfblat=340" (which would... not work, certainly) which then redirects again to "http://www.kingdomofloathing.com/choice.php?forceoption=0". That 0 on the end doesn't look like a promising candidate for the source of KoL knowing what page to give me, I think those redirects are important.

EDIT: Successive visit_url()s on all 3 locations appears to work!
Nice update for my script around the corner :)
 
Last edited:

Veracity

Developer
Staff member
EDIT: Successive visit_url()s on all 3 locations appears to work!
Nice update for my script around the corner :)
Exactly as I expected; "following a redirect" is simply visiting a URL that the server tells you to go to - which is why providing access to "redirect location" and "redirect post mode" seems useful. But if you know up front what you will get, you can simply submit those URLs. Which is precisely what you discovered.

I'm trying to think of an instance where not following a redirect would actually be beneficial to the relay script ... could you highlight an example?
I'm not interested in trying to justify somebody else's code.

Keep in mind that a "RelayRequest" can be submitted either by a relay script or by the browser. In the latter case, we just let the browser do its thing with the redirect.
 
Last edited:

zarqon

Well-known member
At least one of the threads discussing this was mine. Although I understand the reasoning as to why it doesn't always, blindly follow redirects, I have run across multiple instances where it would be very helpful if it did. In my case, it's usually come up when visiting extra-KoL sites. Perhaps redirects could always be automatically followed when visiting sites outside of KoL?

It would probably be reasonable to give a relay script access to this.redirectLocation and this.redirectMethod so you could do the equivalent.

Otherwise, +1 to this, please!
 

Catch-22

Active member
If I may weigh in on this topic as I believe I was partially involved in writing a patch for redirect support in GenericRequests (memory a little foggy though). I believe I wrote this simply because the support for redirects in GenericRequests at the time were pretty basic (only followed 302 I think?). There's no real reason that instanceof RelayRequests aren't being redirected other than I believe more work would've been required to handle them properly and at the time I was only adding support for more "automated" style requests, as Veracity has already noted.

If somebody wants to add support for redirecting RelayRequests I don't think there's any reason not to other than it being a bit more fiddly to get right, I also gather that relay overrides are a lot more popular (and doing a lot more things) than they used to be so people are probably running into this more often.

In summary, the redirect handling for RelayRequests is the same as it always has been (let the browser handle it), I only had the time and resources to write/test a patch that added support for automated request redirects.
 
Last edited:

Veracity

Developer
Staff member
OK, I'm beginning to be convinced that visit_url() - the one with no argument, i.e., the one that a relay script uses to get the "current" page - should follow redirects.

If you look at the Right Side of the Tracks, you see Spookyraven Manor with a link to manor.php.
When you click on it, manor.php redirects to place.php?whichplace=spookyraven1

So, Bale's "manor.php" is called when you click on manor.php, it calls visit_url() and gets a blank page, since it redirects to place.php?whichplace=spookyraven1, and gets a "Index 7 out of bounds (manor.ash, line 66)" when it tries to insert its markup in the blank page.

So, is the solution to have visit_url() follow the redirect automatically - and have the script continue to be manor.ash - or make Bale rename his script to place.ash and handle only whichplace=spookyraven1, thereby conflicting with other scripts that might want to handle other "places"?

I think the former.
 

zarqon

Well-known member
This is a thrilling development. I just had to go through CanAdv and rename several URLs because it was giving different results in relay vs. CLI. Despite knowing that visit_url() presently doesn't follow redirects in a relay script, it took me quite a lot of debug prints and head-scratching to realize that was the source of the problem!
 

Veracity

Developer
Staff member
Revision 12648 makes the no-argument version of visit_url() follow redirections until the request finally results in a response.
 

Bale

Minion
I'm pretty happy that my manor.ash override works again. I really wasn't looking forward to making a place.ash override.

Thank you.
 
Last edited:
Top