Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo


#267 Error 404 on Cool Reader for OPDS (3rd click)

Vadim Lopatin
David Hooper

Cool Reader needs a bit more smarts put into determining the "relative path" of the opds xml links

I have setup a calibre opds, (and the HTML version is working fine, as is other ebook readers via opds)
However, on the android tablet (in Cool Reader), it shows the main page calibre OPDS page fine, and then the next click works (e.g. "tags")
but when I then choose the next one ("tags starting with z for example) I get the 404

The xml "chain" it has gone through before it fails looks like this
(choose "TAGS")
\Apache2.2\htdocs\opds\_catalog\ 2de82055/2de82055_tags.xml
(this shows the list of tags"
(I choose "starting with z)

I'm therefore, in this folder
\Apache2.2\htdocs\opds\_catalog\ 2de82055/
and the link says

which is effectively the same folder
This is the part where Cool Reader needs some loving. It needs to determine that it is already in that path, and strip out the redundant ../2de2055/ part because it is already in that folder.

Here are the logs showing the html access (ignoring images)
and then the xml access (cool reader opds)
(html access)
"GET /opds/_catalog/index.html HTTP/1.1" 200 35570
"GET /opds/_catalog/header.html HTTP/1.1" 200 175
"GET /opds/_catalog/2de82055/2de82055_tags.html HTTP/1.1" 200 232151
"GET /opds/_catalog/2de82055/2de82055_tags_5a.html HTTP/1.1" 200 23322

(cool reader opds access)
"GET /opds/_catalog/index.xml HTTP/1.1" 200 34396
"GET /opds/_catalog/index.xml HTTP/1.1" 200 34396
"GET /opds/_catalog//2de82055/2de82055_tags.xml HTTP/1.1" 200 233595
"GET /opds/_catalog//2de82055/2de82055/2de82055_tags_5a.xml HTTP/1.1" 404 251

If I inspect the html vs xml file, the actual link in both cases is
so that implies that the client (web browser) is using some smarts to strip that off its' requests, whereas the android app is not.

I can provide a link to my OPDS server if required for testing, or am happy to test for you

p.s, love this app. keep up the good work


  • David Hooper
    David Hooper

    • assigned_to: nobody --> buggins
  • Frank de Lange
    Frank de Lange

    This bug seems to have many forms. It is probably what keeps CoolReader from working with the Owncloud OPDS catalog (https://apps.owncloud.com/content/show.php?content=168132) I made.

    CoolReader connects just fine, and shows the root page without problems. On trying to follow any of the links on that page, the results are less than perfect as it just returns 'Error occurred while reading OPDS catalog' messages. The web server log shows why:

    "GET /example/index.php/apps/files_opds//?id=directory HTTP/1.1" 200 12427 "https://www.example.org/example/index.php/apps/files_opds/" "CoolReader/3(Android)"

    The problem lies with the double slash after files_opds: files_opds//?id=directory

    This extra slash is inserted by CoolReader. Things get even stranger when the OPDS feed url is changed to remove the trailing slash:

    "GET /example/index.php/apps//?id=directory HTTP/1.1" 200 12427 "https://www.example.org/example/index.php/apps/files_opds/" "CoolReader/3(Android)"

    Now CoolReader remove the final directory, replacing it with a slash...

    The links inside the OPDS feed are relative as can be seen by this entry - the one which causes CoolReader to fail.

    Browse catalog
    <content type="text">Browse the catalog in alphabetical order</content>
    <link type="application/atom+xml;profile=opds-catalog;kind=navigation" href="?id=directory"/>

    May I suggest having a look at how FBReader solves this problem? Their OPDS browser has no problems browsing this feed.

  • Frank de Lange
    Frank de Lange

    The problem lies in the logic in OPDSUtil.java, in the LinkInfo class, in the convertHref() method:

                  public static String convertHref( URL baseURL, String href ) {
                            if ( href==null )
                                    return href;
                            String port = "";
                            if (baseURL.getPort() != 80 && baseURL.getPort() > 0)
                                    port = ":" + baseURL.getPort();
                            String hostPort = baseURL.getHost() + port;
                            if ( href.startsWith("/") )
                                    return baseURL.getProtocol() + "://" + hostPort + href;
                            if ( !href.startsWith("http://") ) {
                                    return baseURL.getProtocol() + "://" + hostPort + dirPath(baseURL.getPath()) + "/" + href;
                            return href;

    dirPath(baseURL.getPath()) does not work as intended, especially in combination with the extra slash which is added afterwards. Just removing that extra slash will solve the problem CoolReader has with the OPDS catalog feed from my Owncloud app, as long as the feed url was specified with a trailing slash.

    Last edit: Frank de Lange 2014-12-11
  • Vadim Lopatin
    Vadim Lopatin

    Thanks! Will try to fix asap.

  • Vadim Lopatin
    Vadim Lopatin

    • labels: OPDS --> OPDS, Android
    • status: open --> pending
    • Priority: 5 --> 1