Ugg, not sure what's wrong with the forum but it keeps taking me to a "Something went wrong page" and now it is chopping off the bottom of my code sample, removing the [/code] tag.
Tried in Firefox and Chrome, so must be something server-side.
Printable View
Ugg, not sure what's wrong with the forum but it keeps taking me to a "Something went wrong page" and now it is chopping off the bottom of my code sample, removing the [/code] tag.
Tried in Firefox and Chrome, so must be something server-side.
Just added a new feature at the GitHub repository, a CBuilderFile class that helps you easily send file data downstream to the browser from your FCGI applications.
It automatically builds HTTP header fields for Content-Length, Content-Type (based on a partial list of MIME type to File Extension mappings) etc...
It can also detect if the browser's cached copy matches the server-side copy (based on ETag/If-None-Match values) and send back HTTP 304 Not Modified instead of the entire file data.
Please see the included VbFcgiApp demo for an example of its usage.
Right now the Etag is being calculated by combining the file path, size, and last modified date and then hashing that data. This isn't perfect, but it should work OK until I can hash actual file data.
CAUTION BINARY COMPATIBILITY BROKEN AGAIN.
CAUTION - BINARY COMPATIBILITY HAS BEEN BROKEN.
Big new update to VbFcgiLib here: https://github.com/jpbro/VbFcgi
The biggest new addition is support for .VBML files.
What are VBML files? They are text files (typically HTML documents) that site in your web server's document root folder and include special tags. When VbFcgiLib encounters these tags, it raises a FoundTag event in your FCGI application class. You can then perform any sort of dynamic processing that you'd like and pass a replacement value back. VbFcgiLib will then replace the tag with your dynamic content. The best part is that you can easily edit VBML files in your favourite text editor and changes will be reflected live without needing to rebuild your FCGI application or restart your web server.
For example, this VBML file:
This document has 3 tags: [[TITLE]], [[TABLE_001]], and [[SAMPLE_UNKNOWN_TAG]].Code:<!DOCTYPE html>
<head>
<title>[[TITLE]]</title>
<style>
td
{
padding: 10px;
border: 1px solid #d0d0d0;
}
.right
{
text-align: right;
}
</style>
</head>
<body>
<h1>This is a table of random numbers generated dynamically in a VB6 FCGI application:</h1>
[[TABLE_001]]
<p>[[SAMPLE UNKNOWN TAG]]</p>
</body>
</html>
Your FCGI application will receive 3 FoundTag events that pass TITLE, TABLE_001, and SAMPLE_UNKNOWN_TAG as tag values. You can use the passed CWebStringTemplate class to build plain text or HTML text. Once built, your dynamic text will replace the tag text. Once all tags have been processed, all the content will be sent to the browser.
So some VB code like this:
Will be turned into this:Code:Private Sub mo_Vbml_FoundTag(ByVal p_Tag As String, po_Replacement As VbFcgiLib.CWebStringTemplate, ByRef p_DoNotReplace As Boolean)
Dim ii As Long
Dim l_OpenTagIndex As Long
Select Case UCase$(p_Tag)
Case "TITLE"
' Generate a dynamic title
po_Replacement = "Welcome on " & Format$(Now, "MMMM D, YYYY at H:NN ampm")
Case "TABLE_001"
' Generate a random table of data, and tell the VBML template parser not to encode HTML entities on the assumption we've done it ourselves
With po_Replacement
.SkipEncodeEntities = True ' Turn off automatic entity encoding since we are building HTML
.OpenTags "table"
For ii = 0 To 5
l_OpenTagIndex = .OpenTags("tr")
.AppendWithTag Chr$(65 + ii), "td"
.AppendWithTagAndAttributes Format$(Rnd * 100, "0.000"), "td", "right"
.AppendWithTagAndAttributes Format$(Rnd * 100, "0.000"), "td", "right"
.AppendWithTagAndAttributes Format$(Rnd * 100, "0.000"), "td", "right"
.CloseOpenedTagsToIndex l_OpenTagIndex ' Close the <tr> tag
.Append vbNewLine
Next ii
.CloseAllOpenedTags
End With
Case Else
' Unknown tag
apiOutputDebugString "Encountered unknown tag: " & p_Tag
po_Replacement.SkipEncodeEntities = True ' Turn off automatic entity encoding since we are building HTML
po_Replacement = "<b style='color: red'>UNKNOWN TAG WARNING:</b> <i>«" & p_Tag & "»</i>"
End Select
End Sub
Attachment 154707
Enjoy :)
I've been adding a lot of PURPOSE and USAGE comments to the various VbFcgiLib classes that I hope will help introduce you to the library, so please give them a read over at GitHub.
Of course, I'm more than happy to answer questions here should there be any.
Thank you very much, Jason.
I'm curious to try it, so during the holidays I hope to find the time to do some tests.
Hi gibra, it will be nice to get some feedback. I look forward to your comments and questions once you've found a chance to it it a try! Hope you enjoy it :)
I've added a JSON builder/helper class and updated the demo app to include some new demonstrations (JSON and VBML templates).
Binary compatibility was broken again.
I've updated the demo application to better illustrate how you can build modern looking & performing websites using VBFCGI/VB6 backend, with VBML templates along with technologies like Jquery, Bootstrap, JSON & AJAX.
Result looks like this:
Attachment 154857
Thought I pose this as a question in case anyone out there had an insights/preferences.
Consider the following URL:
http://localhost/myapp.fcgi?test
Where test is the query string.
In the current VbFcgi implementation, test is treated as a default parameter value. Calling CHttpQueryParams.DefaultValue returns test, and calling CHttpQueryParams.ValuesByKey("") returns a CHttpQueryParamValues object with a single value of test.
I'm thinking it might be better to treat test as a "flag" and use it as a key instead of a value. So calling CHttpQueryParams.Exists("test") would return True and calling CHttpQueryParams.ValuesByKey("test") would return a CHttpQueryParamValues object with zero values.
Perhaps the best of both worlds would be an option property to let users decide which approach to take based on the needs of their FCGI applications?
Thoughts anyone?
My audio-subtitle editing tool will be completed soon, I'm going to start learning and testing your framework next week.
Sorry for spamming everyone subscribed to this thread - there's nothing new in the framework, but I tried to send a private message to jg.sa regarding our conversations here since they spawned the idea to open-source the VBFCGI code. I haven't heard from them since, and unfortunately their private mailbox was full.
If jg.sa is still reading: Have you had a chance to try out the FCGI framework? If so, how are things working out? I'm interested in your feedback. Cheers! :)
Hi jpbro, I checked your source code yesterday, but I failed to install nginx and I'm looking for the reason for the failure. After I install nginx successfully, I'll begin to write some test procedures. I'd like to use your framework to develop a Web-Login module.
Hi dreammanor,
There could be few reasons for nginx not working...
- If you are running any other web server (like IIS for example), then that server has likely already bound to port 80 and this would cause the second attempt by Nginx to fail (unless you change the Nginx port to something else).
- It could be that your firewall or antivirus/security software is blocking Nginx?
For testing purpose you might want to try using the version I have included in my GitHub repository in the /bin/nginx folder. It doesn't need installation, you can just run it from the Command Line. e.g.:
Once it is running you can go to the following page in your browser:Code:> C:\VbFcgi\bin\nginx\nginx.exe
http://127.0.0.1
And you should see a Welcome to nginx! message page. If you get that far, then you have a working local dev instance of Nginx running that you can use. The configuration file I've included is set up for a single FCGI web app listener on port 9100, so the command line to start your web app will be:
Once that is spawned you can test if the demo FCGI app is working by going here:Code:> C:\VbFcgi\bin\VbFcgiHost.exe /port 9100 /spawn 1
http://127.0.0.1/vbfcgiapp.fcgi
At which point you should the the VBFCGI demo web page.
Hope that helps, but let me know if you still have any issues.
Hi jpbro, the error message is as follows:
Directory problem has been resolved, I'm working on permissions issues:
Edit:
I'm now testing some of the solutions found on the Internet.
Sounds like a firewall or antivirus might be blocking Nginx...Some info on error 10013 :
https://answers.microsoft.com/en-us/...7e4eddc?auth=1
Glad you got the Nginx portion working :)
Let me know if you have any issues going forward with your web app and I will do what I can to help.
Coming soon: I've done a bit of work on a demo to show how you can get data from a VB6 form downstream to a web browser using the VbFcgi framework based on comments in the following thread: http://www.vbforums.com/showthread.p...B6-app-FastCGI
Note that I don't recommend this approach for new development, or for long-term deployment. Think of it as a stop-gap measure so you can more quickly get your existing applications on the web for testing, but for the long-term you should be looking to move the functionality out of forms and into classes and/or standard modules.
Anyway, I have a bit of cleanup to do, but I will try to get this published to the VBFcgi GitHub repository soon.
In the meantime here's a screenshot to whet your appetite!
Attachment 155837
ALSO AN IMPORTANT NOTE: The VB6 form shown above is NOT being displayed in the browser (it is a separate EXE running). Also, the VB6 form will NOT be showing when used with your FCGI application (it will be loaded but not shown, and interacted with while invisible). In fact you should never show any form from your FCGI application as it will be running unattended.
Hi jpbro, I also need your demo, thanks very much.
Also, when I send the URL http://127.0.0.1/vbfcgiapp.fcgi?json_getdata to the browser, the page can be displayed normally. But when I clicked the button "Request Table Data from Server" at the bottom of the page, the page did not show Json data.
Another question, in addition to using OutputDebugString, I wonder if there are any better ways to debug vbFcgiLib.dll and vbFcgiApp.dll?
@dreammanor - I've just published the Browser<>VB6 Form interfacing demo to GitHub.
re: the "Request Table Data" problem - is it possible that your browser is blocking javascript for 127.0.0.1? If you can confirm that Javascript is allowed, what browser and version are you using? I'll run some tests.
Regarding the OutputDebugString debugging - There might be a better way, but I'm not sure (don't know if there would be an effective way to have a "stepping" debugger when working against the browser - the browser would probably timeout while you are stepping through even if it were possible).
One thing we could do though is write short test subs for things are want to try out...then you can run the test method and step through the code in the IDE. I think adding some a debug flag to the po_Response object so you can see exactly what data is being written to the pipe might be helpful with this too.
I'm open to any bright ideas about this from anyone though.
Thanks for the feedback :)
I tested the new Demo, the pictures on the VB6 Form still can not be displayed on the page.
I checked my browser settings, JavaScript is not blocked. But I don't know how to check if JavaScript is blocked only for 127.0.0.1. My browser is Chrome, version: 64.0.3282.140 (64 bit)
It seems Olaf said that he has better debugging methods.
Interesting...I just tried in Chrome and the Browser<>VB6 form interfacing is only partially working (getting the ListBox content is OK, but the PictureBox image is not). That part of the demo works fine in Firefox and Edge, so I'll have to do some more testing to see if I can figure out what's going wrong in Chrome. Strangely, I don't have a problem with the "Request Data" method in Chrome though? Always fun working with the various browsers!
Looks like I was wrong in the last post - I had some stale/corrupt cache files in Chrome from an earlier test so that's why the image demo wasn't working. After clearing the cache, everything works fine in Chrome, Firefox, & Edge.
Are things working for you in browsers other than Chrome?
I cleared the cached files in Chrome & Edge and re-tested, the Demo still can't display the picture. I'll install a Firefox browser to test it.
Also, I would like to download the Json data returned by FastCGI via WinHttp and display it in a VB6 TextBox, but I didn't get the Json data. Here is my test code:
Code:Private Sub Form_Click()
Dim jsonData As String
jsonData = GetJsonDataFromFastCGI()
MsgBox jsonData
End Sub
Private Function GetJsonDataFromFastCGI() As String
Dim Req As Object: Dim B() As Byte
Set Req = CreateObject("Winhttp.WinHttpRequest.5.1")
With Req
.Open "POST", "http://127.0.0.1:8080/vbfcgiapp.fcgi?json_getdata", False
.SetRequestHeader "Content-Type", "application/json"
.Send vbNullString
B = .ResponseBody
End With
If B(0) = 123 Then
Err.Raise vbObjectError, , StrConv(B, vbUnicode)
Else
GetJsonDataFromFastCGI = StrConv(B, vbUnicode)
End If
End Function
Hi dreammanor - try this instead (it works for me):
The 2 changes I made are:Code:Option Explicit
Private Sub Form_Click()
Dim jsonData As String
jsonData = GetJsonDataFromFastCGI()
MsgBox jsonData
End Sub
Private Function GetJsonDataFromFastCGI() As String
Dim Req As Object: Dim B() As Byte
Set Req = CreateObject("Winhttp.WinHttpRequest.5.1")
With Req
.Open "POST", "http://127.0.0.1:8080/vbfcgiapp.fcgi?json_getdata=json_getdata", False
.SetRequestHeader "Content-Type", "application/json"
.Send vbNullString
B = .ResponseBody
End With
If B(0) <> 123 Then
Err.Raise vbObjectError, , StrConv(B, vbUnicode)
Else
GetJsonDataFromFastCGI = StrConv(B, vbUnicode)
End If
End Function
- Pass a key and value for the "json_getdata" query. This is because keys and values are currently required by the framework. This doesn't appear to be neccessary by any RFI or anything, so looks like a good candidate for an enhancement to the framework.
- Test B(0) <> 123 instead of testing B(0) = 123 since we want JSON the error condition should only exist if our first character isn't "["
Hope that helps!
Looks like I've already encountered the issue of "valueless" query keys as an open question at GitHub:
https://github.com/jpbro/VbFcgi/issues/13
Great, it works fine. My first (and most important) goal has been fully achieved. Next, I'll begin to learn how to generate dynamic web pages, I want all the web pages are dynamically generated. Thank you so much, jpbro.
In addition, could FastCGI return binary-data? So I can return the database recordset to client side directly.
You can send raw Byte data downstream from the IFcgiApp_ProcessRequest method as follows:
For RC5 recordsets specifically, you can also write JSON downstream as follows:Code:po_Response.WriteBytes MyByteArray ' Where my byte array is any byte data
po_Response.Finished
Code:' Build JSON response where lo_Rs is a vbRichClient5.cRecordset obje
Dim lo_Json As VbFcgiLib.CBuilderJson
Set lo_Json = po_Response.Builders.Builder(builder_Json)
lo_Json.Initialize lo_Rs.ToJSONUTF8
lo_Json.Finish
I've tested the demo in Firefox, it still can't display the picture. But it doesn't matter, maybe there's something wrong with my computer configuration.
In addition, the test.png file seems to be damaged, it can't be displayed on my computer.
About the query parameters, I have an idea:
Could we turn the URLs(URIs) of FastCGI into a standard Web-API form? E.g:
127.0.0.1/api/products
127.0.0.1/api/products/id
127.0.0.1/api/products/?category=category
Thanks for that info - the test.png file does seem broken on GitHub - maybe it didn't get transferred as a binary file? I'll see if I can fix it.
What if you replace the test.png file with a known working PNG file? Does it work then?
You can configure the server section of your nginx.conf to rewrite addresses like the above into HTTP query strings that VBFCGI will understand. For example, something like this (untested, but I think it will work):
Would redirect URLs like http://127.0.0.1/api/products/id/1234567 to 127.0.0.1/nomad.fcgi?action=showproducts;productid=1234567Code:rewrite ^(/api/products/id/)([0-9]+) "nomad.fcgi?action=showproducts;productid=$2" last;
The [0-9]+ part is a regex that matches any sequence of integers 1 or more characters long.
Yes, if I replace the test.png file with a known working PNG file, it works fine.
I haven't tested it yet because the query string I entered in the URL is always unresponsive. I wrote a test procedure, but it still didn't work.
Code:Private Sub IFcgiApp_ProcessRequest(po_Request As VbFcgiLib.CFcgiRequest, po_Response As VbFcgiLib.CFcgiResponse)
ShowHttpQueryParameters po_Request, po_Response
End Sub
Private Sub ShowHttpQueryParameters(po_Request As VbFcgiLib.CFcgiRequest, po_Response As VbFcgiLib.CFcgiResponse)
Dim ii As Long
Dim lo_Json As VbFcgiLib.CBuilderJson
Set lo_Json = po_Response.Builders.Builder(builder_Json)
lo_Json.Initialize Nothing ' Initialize to empty collection
lo_Json.IJsonObject.AddJsonObjectByKeyValuePairs "sub", "ShowHttpQueryParameters"
With po_Request.Http.QueryParameters
For ii = 0 To .KeyCount - 1
lo_Json.IJsonObject.AddJsonObjectByKeyValuePairs .KeyByIndex(ii), .ValuesByIndex(ii)
Next ii
End With
lo_Json.Finish
End Sub
It looks like I can't add a JSONObject RC5 collection to another JSON Object RC5 collection and have it maintain its overall JSONObject state. This causes the result of SerializeToJSON* to return an empty JSON Object string ("{}"). I'll come up with a workaround ASAP - thanks for posting the code that demonstrates the problem.
Alright, so I think the issue is that JSON objects & arrays that are children of a JSON object must be named/keyed, and the current AddJsonObjectByKeyValuePairs method doesn't take a "name/key" parameter.
There are a couple of options - add a Name/Key parameter (which will break binary compatibility), add a new method that has a Name/Key parameters and will maintain binary compatibility (maybe AddJsonObjectByNameAndKeyValuePairs), or perhaps try to dynamically generate a random name for the the JSON object/array being added when they are being added to an existing JSONObject. I'll have to give this a bit of thought.
Thank you jpbro, you did a lot for us.
Hi dreammanor, happy to help :)
I've pushed some changes to the JSON builder/helper class that I hope will do the trick. Now when you want to add array or object data to an existing JSON object collection, the first passed value to AddJsonObjectByKeyValuePairs or IJson_AddJsonArrayByValues should be a string that will act as the object/array name within the parent JSON object.
Here's how I've rewritten your code to accommodate the new approach:
Hope that helps, but let me know if you encounter any further issues. Thanks for reporting the problem!Code:Private Sub IFcgiApp_ProcessRequest(po_Request As VbFcgiLib.CFcgiRequest, po_Response As VbFcgiLib.CFcgiResponse)
ShowHttpQueryParameters po_Request, po_Response
End Sub
Private Sub ShowHttpQueryParameters(po_Request As VbFcgiLib.CFcgiRequest, po_Response As VbFcgiLib.CFcgiResponse)
Dim ii As Long
Dim lo_Json As VbFcgiLib.CBuilderJson
Set lo_Json = po_Response.Builders.Builder(builder_Json)
lo_Json.IJsonObject.AddJsonObjectByKeyValuePairs "sub", "ShowHttpQueryParameters"
With po_Request.Http.QueryParameters
For ii = 0 To .KeyCount - 1
lo_Json.IJsonObject.AddJsonObjectByKeyValuePairs "Query" & ii+1, .KeyByIndex(ii), .ValuesByIndex(ii)
Next ii
End With
lo_Json.Finish
End Sub
Thank you so much, jpbro. I'll test it and feed back the test results.