 
      - parameter prefix: The URI prefix associated with the container (by `addEpub`)
      */
-    open func removeEpub(withEndpoint endpoint: String) {
+    public func removeEpub(withEndpoint endpoint: String) {
         if containers[endpoint] != nil {
             containers[endpoint] = nil
             publications[endpoint] = nil
             // TODO: remove handlers
         }
     }
+
+    // MARK: - Internal methods
+
+    /// Append a link to self in the given Publication links
+    ///
+    /// - Parameters:
+    ///   - publication: The targeted publication.
+    ///   - endPoint: The URI prefix to use to fetch assets from the publication.
+    internal func addSelfLinkTo(publication: Publication, endpoint: String) {
+        guard let baseURL = baseURL else {
+            return
+        }
+        let manifestPath = "\(endpoint)/manifest.json"
+        let publicationURL = baseURL.appendingPathComponent(manifestPath,
+                                                            isDirectory: false)
+        let link = Link(href: publicationURL.absoluteString,
+                        typeLink: "application/webpub+json", rel: "self")
+
+        publication.links.append(link)
+    }
+
 }

    case epubParser(underlayingError: Error)
}

/**
 The HTTP server for the publication's manifests and assets
 */
open class EpubServer {

    /// The HTTP server

        }
        do {
            parser = try EpubParser(container: container)
            publication = try parser.parse()
        } catch {
            throw EpubServerError.epubParser(underlayingError: error)
        }
        // newverstart
        // Add self link
        addSelfLinkTo(publication: publication, endpoint: endpoint)

        // Are these dictionaries really necessary?
        containers[endpoint] = container
        publications[endpoint] = publication

        let fetcher = EpubFetcher(publication: publication, container: container)

        // Add the handler for the resources OPTIONS
        /*
         webServer.addHandler(
         forMethod: "OPTIONS",
         pathRegex: "/\(endpoint)/.*",
         request: GCDWebServerRequest.self,
         processBlock: { request in

         guard let path = request?.path else {
         NSLog("no path in options request")
         return GCDWebServerErrorResponse(statusCode: 500)
         }

         NSLog("options request \(path)")

         return GCDWebServerDataResponse()
         })
         */

        // Add the handler for the resources
        webServer.addHandler(
            forMethod: "GET",
            pathRegex: "/\(endpoint)/.*",
            request: GCDWebServerRequest.self,
            processBlock: { request in

                guard request != nil else {
                    NSLog("no request")
                    return GCDWebServerErrorResponse(statusCode: 500)
                }

                //NSLog("request \(request)")
                //NSLog("request headers \(request!.headers)")

                guard let path = request?.path else {
                    NSLog("no path in request")
                    return GCDWebServerErrorResponse(statusCode: 500)
                }

                NSLog("request \(path)")

                // Remove the prefix from the URI
                let relativePath = path.substring(from: path.index(endpoint.endIndex, offsetBy: 3))
                let resource = publication.resource(withRelativePath: relativePath)
                let contentType = resource?.typeLink ?? "application/octet-stream"

                var response: GCDWebServerResponse
                do {
                    // Get a data input stream from the fetcher
                    if let dataStream = try fetcher?.dataStream(forRelativePath: relativePath) {
                        let range: NSRange? = request!.hasByteRange() ? request!.byteRange : nil
                        let r = WebServerResourceResponse(inputStream: dataStream, range: range, contentType: contentType)
                        response = r
                    } else {
                        // Error getting the data stream
                        NSLog("Unable to get a data stream from the fetcher")
                        response = GCDWebServerErrorResponse(statusCode: 500)
                    }

                } catch EpubFetcherError.missingFile {
                    // File not found
                    response = GCDWebServerErrorResponse(statusCode: 404)

                } catch {
                    // Any other error
                    NSLog("General error creating the response \(error)")
                    response = GCDWebServerErrorResponse(statusCode: 500)
                }

                return response
        })

        // Add the handler for the manifest
        webServer.addHandler(
            forMethod: "GET",
            pathRegex: "/\(endpoint)/manifest.json",
            request: GCDWebServerRequest.self,
            processBlock: { request in
                let manifestJSON = publication.toJSONString()
                let manifestData = manifestJSON?.data(using: .utf8)
                return GCDWebServerDataResponse(data: manifestData, contentType: "application/webpub+json; charset=utf-8")
        })


        // newverend

//        if let publication = try? parser.parse() {
//
//            // Add self link
//            if let pubURL = baseURL?.appendingPathComponent("\(endpoint)/manifest.json", isDirectory: false) {
//                publication.links.append(Link(href: pubURL.absoluteString, typeLink: "application/webpub+json", rel: "self"))
//            }
//
//            // Are these dictionaries really necessary?
//            containers[endpoint] = container
//            publications[endpoint] = publication
//
//            let fetcher = EpubFetcher(publication: publication, container: container)
//
//            // Add the handler for the resources OPTIONS
//            /*
//             webServer.addHandler(
//             forMethod: "OPTIONS",
//             pathRegex: "/\(endpoint)/.*",
//             request: GCDWebServerRequest.self,
//             processBlock: { request in
//
//             guard let path = request?.path else {
//             NSLog("no path in options request")
//             return GCDWebServerErrorResponse(statusCode: 500)
//             }
//
//             NSLog("options request \(path)")
//
//             return GCDWebServerDataResponse()
//             })
//             */
//
//            // Add the handler for the resources
//            webServer.addHandler(
//                forMethod: "GET",
//                pathRegex: "/\(endpoint)/.*",
//                request: GCDWebServerRequest.self,
//                processBlock: { request in
//
//                    guard request != nil else {
//                        NSLog("no request")
//                        return GCDWebServerErrorResponse(statusCode: 500)
//                    }
//
//                    //NSLog("request \(request)")
//                    //NSLog("request headers \(request!.headers)")
//
//                    guard let path = request?.path else {
//                        NSLog("no path in request")
//                        return GCDWebServerErrorResponse(statusCode: 500)
//                    }
//
//                    NSLog("request \(path)")
//
//                    // Remove the prefix from the URI
//                    let relativePath = path.substring(from: path.index(endpoint.endIndex, offsetBy: 3))
//                    let resource = publication.resource(withRelativePath: relativePath)
//                    let contentType = resource?.typeLink ?? "application/octet-stream"
//
//                    var response: GCDWebServerResponse
//                    do {
//                        // Get a data input stream from the fetcher
//                        if let dataStream = try fetcher?.dataStream(forRelativePath: relativePath) {
//                            let range: NSRange? = request!.hasByteRange() ? request!.byteRange : nil
//                            let r = WebServerResourceResponse(inputStream: dataStream, range: range, contentType: contentType)
//                            response = r
//                        } else {
//                            // Error getting the data stream
//                            NSLog("Unable to get a data stream from the fetcher")
//                            response = GCDWebServerErrorResponse(statusCode: 500)
//                        }
//
//                    } catch EpubFetcherError.missingFile {
//                        // File not found
//                        response = GCDWebServerErrorResponse(statusCode: 404)
//
//                    } catch {
//                        // Any other error
//                        NSLog("General error creating the response \(error)")
//                        response = GCDWebServerErrorResponse(statusCode: 500)
//                    }
//
//                    return response
//            })
//
//            // Add the handler for the manifest
//            webServer.addHandler(
//                forMethod: "GET",
//                pathRegex: "/\(endpoint)/manifest.json",
//                request: GCDWebServerRequest.self,
//                processBlock: { request in
//                    let manifestJSON = publication.toJSONString()
//                    let manifestData = manifestJSON?.data(using: .utf8)
//                    return GCDWebServerDataResponse(data: manifestData, contentType: "application/webpub+json; charset=utf-8")
//            })
//
//        }
    }

    /**
