0
votes

I am building a API in r that returns a specific image to the browser from a parsed url.

Currently, the browser shows the base64 encoded string instead of rendering the image.

This is a reproducible example:

    #### Reproducable Example for Stack-Overflow


library("plyr")
library("Cairo")
require("png")
library("base64enc")


# Always 'listening' server for returning image of mtcars dataset
Test_server <- function(){
  while(TRUE){
    writeLines("Listening...")
    CON <- socketConnection(host="localhost", port = 6011, blocking=TRUE, 
                            server=TRUE, open="r+")

    New_Request <- readLines(CON, 3)
    print(New_Request)

    Search <- strsplit(New_Request[1], split="/")[[1]][2]
    print(Search)

    IMG_Name <- paste0(Search, ".png")

    CairoPNG(IMG_Name, width=640, height=450)
    plot(mtcars[Search])
    IMG_TEST <- Cairo.capture()
#     dev.off()


    IMG_data <- dataURI(writePNG(IMG_TEST), mime="image/png")


    ### I have tried the following commands to print the IMAGE not the base64 to the browser:

#   SEND_img <- paste0("<img width='640' height='450' src='", IMG_data, "'></img>")
#   SEND_img <- paste0('<img src="', IMG_data, '"/>')
    SEND_img <- cat(sprintf("<img src=\"%s\" />", IMG_data), file=CON)
#   writeLines(SEND_img, CON)


    #Remember to close the connection! 
    close(CON)
  }
}


# Now run the server
Test_server()

When you run the server, go to

    http://127.0.0.1:6011/mpg/ 

or

    http:http://127.0.0.1:6011/disp/

The browser will show you the base64 inside in a pre tag. How can I have all (modern) browsers display the image from this API?

Thanks!


EDIT: The new working code is the following;

# Always 'listening' server for returning image of mtcars dataset
Test_server <- function(){
  while(TRUE){
    writeLines("Listening...")
    CON <- socketConnection(host="localhost", port = 6011, blocking=TRUE, 
                            server=TRUE, open="a+b")


    New_Request <- readLines(CON, 3)
    print(New_Request)

    Search <- strsplit(New_Request[1], split="/")[[1]][2]
    print(Search)

    if (Search != "favicon.ico HTTP") {

      IMG_Name <- paste0(Search, ".png")

      CairoPNG(IMG_Name, width=640, height=450)
      plot(mtcars[Search])
      IMG_TEST <- Cairo.capture()
      dev.off()


      IMG_data <- dataURI(writePNG(IMG_TEST), mime="image/png")

      SEND_img <- cat(sprintf("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<img src=\"%s\" />", IMG_data), file=CON) 

    }
    #Remember to close the connection! 
    close(CON)
  }
}


# Now run the server
Test_server()
1
No one knows anything about base64?JayCo

1 Answers

1
votes

You need HTTP headers, including one that sets the content type to text/html, otherwise the browser doesn't know what to make of the response. It's kind of bizarre that any browser would show anything for an HTTP response with no headers, actually.

Replace the SEND_img line with this:

SEND_img <- cat(sprintf("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<img src=\"%s\" />", IMG_data), file=CON)