How do I tell HTTP Server where "parameters" begin in URI?
-
- Posts: 9
- Joined: Thu Jan 05, 2023 8:03 pm
How do I tell HTTP Server where "parameters" begin in URI?
I am making my first attempt at creating a web service based on the DIY section of the article "Providing RPG Web Services on IBM i".
So far I have:
1) Created a new HTTP Server called RESTFUL
2) Created a new IBM i library called RESTFUL
3) Created a SQLRPGLE program in the RESTFUL library called TSTCONNECT
I want to invoke the TSTCONNECT program from the web and pass filter parameters with a URI similar to:
http://address:port/tstconnect/{item}/{size}/{desc}/{hide}
NOTE: Any of the parameters {item}, {size}, {desc}, {hide} can be unnecessary to the request. I don't know how to indicate that in the URL. How do I indicate "no specific item selected" but still request a specific {size} in the URL? Do I need some kind of filler character(s) in the URL to indicate "no selection"?
In order to test the TSTCONNECT program with the Postman app, I have added the following to the configuration file for HTTP server RESTFUL:
ScriptAlias /tstconnect/ /qsys.lib/restful.lib/tstconnect.pgm
<Directory /qsys.lib/restful.lib>
Require all granted
</Directory>
With those pieces in place, I have used Postman to invoke the following URI:
http://address:port/tstconnect/13142/51/ASTER:SHOWMAKERS%20INDIGO%20ICE/hide=false
The response I am getting from Postman is:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML>
<HEAD>
<TITLE>403 Forbidden</TITLE>
</HEAD>
<BODY>
<H1>Forbidden</H1>
<p>You don't have permission to access this resource.</p>
</body>
</html>
The resulting entry in the access.log is:
... [09/Jul/2024:23:14:08 -0400] "GET /tstconnect/13142/51/ASTER:SHOWMAKERS%20INDIGO%20ICE/hide=false HTTP/1.1" 403 199 "-" "PostmanRuntime/7.40.0"
And the resulting entry in the error log is:
[Tue Jul 09 23:14:08.151624 2024] [core:error] [pid 58734:tid 000003B7] (3486)A path name is too long.: [client 10.151.151.14:56129] ZSRV_MSG064C: access to /tstconnect/13142/51/ASTER:SHOWMAKERS INDIGO ICE/hide=false failed (filesystem path 'Ìþ')
I am now officially in over my head. Help?
So far I have:
1) Created a new HTTP Server called RESTFUL
2) Created a new IBM i library called RESTFUL
3) Created a SQLRPGLE program in the RESTFUL library called TSTCONNECT
I want to invoke the TSTCONNECT program from the web and pass filter parameters with a URI similar to:
http://address:port/tstconnect/{item}/{size}/{desc}/{hide}
NOTE: Any of the parameters {item}, {size}, {desc}, {hide} can be unnecessary to the request. I don't know how to indicate that in the URL. How do I indicate "no specific item selected" but still request a specific {size} in the URL? Do I need some kind of filler character(s) in the URL to indicate "no selection"?
In order to test the TSTCONNECT program with the Postman app, I have added the following to the configuration file for HTTP server RESTFUL:
ScriptAlias /tstconnect/ /qsys.lib/restful.lib/tstconnect.pgm
<Directory /qsys.lib/restful.lib>
Require all granted
</Directory>
With those pieces in place, I have used Postman to invoke the following URI:
http://address:port/tstconnect/13142/51/ASTER:SHOWMAKERS%20INDIGO%20ICE/hide=false
The response I am getting from Postman is:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML>
<HEAD>
<TITLE>403 Forbidden</TITLE>
</HEAD>
<BODY>
<H1>Forbidden</H1>
<p>You don't have permission to access this resource.</p>
</body>
</html>
The resulting entry in the access.log is:
... [09/Jul/2024:23:14:08 -0400] "GET /tstconnect/13142/51/ASTER:SHOWMAKERS%20INDIGO%20ICE/hide=false HTTP/1.1" 403 199 "-" "PostmanRuntime/7.40.0"
And the resulting entry in the error log is:
[Tue Jul 09 23:14:08.151624 2024] [core:error] [pid 58734:tid 000003B7] (3486)A path name is too long.: [client 10.151.151.14:56129] ZSRV_MSG064C: access to /tstconnect/13142/51/ASTER:SHOWMAKERS INDIGO ICE/hide=false failed (filesystem path 'Ìþ')
I am now officially in over my head. Help?
-
- Site Admin
- Posts: 872
- Joined: Sun Jul 04, 2021 5:12 am
Re: How do I tell HTTP Server where "parameters" begin in URI?
I'm guessing you wanted the URL to be as follows:
The ? character separates the path portion of the URL and the query-string portion. "hide=false" would be a query string
Code: Select all
http://address:port/tstconnect/13142/51/ASTER:SHOWMAKERS%20INDIGO%20ICE?hide=false
-
- Posts: 9
- Joined: Thu Jan 05, 2023 8:03 pm
Re: How do I tell HTTP Server where "parameters" begin in URI?
EDIT: Would I be better off to forget about passing the parameters in the URI and instead put them in a JSON request file and process it as standard input? If so, which presentations can I peruse to get me down that path?
___
I am trying to pass four parameters to the program by following the example below from page 58 of the "Providing RPG Web Services on IBM i" presentation.
• Browser connects to: ibmi.example.com
• Apache sees the /cust and calls RESTFUL/CUSTINFO
• Our program can read the 495 (customer number) from the URL itself.
In my case I have added three additional parameters, all separated by a forward slash. I tested the following URI in Postman.
Postman gets the following results:
The message in the error log on IFS tells me...
It doesn't appear to like the parameters in the URL following "/tstconnect".
___
I am trying to pass four parameters to the program by following the example below from page 58 of the "Providing RPG Web Services on IBM i" presentation.
Code: Select all
http://ibmi.example.com/cust/495
• Apache sees the /cust and calls RESTFUL/CUSTINFO
• Our program can read the 495 (customer number) from the URL itself.
In my case I have added three additional parameters, all separated by a forward slash. I tested the following URI in Postman.
Code: Select all
GET http://address:port/tstconnect/13142/102/ASTER/false
Code: Select all
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML>
<HEAD>
<TITLE>403 Forbidden</TITLE>
</HEAD>
<BODY>
<H1>Forbidden</H1>
<p>You don't have permission to access this resource.</p>
</body>
</html>
Code: Select all
[Wed Jul 10 10:05:17.063888 2024] [core:error] [pid 58734:tid 000003B7] (3486)A path name is too long.: [client **.***.***.**:*****] ZSRV_MSG064C: access to /tstconnect/13142/102/ASTER/false failed (filesystem path 'Ìþ')
-
- Site Admin
- Posts: 872
- Joined: Sun Jul 04, 2021 5:12 am
Re: How do I tell HTTP Server where "parameters" begin in URI?
For some reason, your scriptalias doesn't seem to be working. It is trying to access /tstconnect/13142/102/ASTER/false in the IFS, and it doesn't have permission to access that -- which is why you are getting a 403 error. (403 is an authority error.)
I don't know why that would be, it's not clear from what you've posted. I will try your ScriptAlias statements and see if I can reproduce it when I have time to do so.
Sending the data in a json document in the body of the request would not solve this problem.
The way you're doing this should work. That said, this does not comply with the REST architecture guidelines/recommendations. It'll work, but you can't really call it REST if done this way. The URI is supposed to identify the resource you're working with. The key word is IDENTIFY -- i.e. it should be the "unique key" that identifies whatever you are working with -- it should NOT contain all of the "fields of data" that goes with whatever you are working with. The data should be sent in the body, such as with a JSON document (recommended) or XML (today, typically only used for compatability with old software.) But the REST architecture doesn't care what the format of the body is -- just that it is where you transmit the details.
I don't know why that would be, it's not clear from what you've posted. I will try your ScriptAlias statements and see if I can reproduce it when I have time to do so.
Sending the data in a json document in the body of the request would not solve this problem.
The way you're doing this should work. That said, this does not comply with the REST architecture guidelines/recommendations. It'll work, but you can't really call it REST if done this way. The URI is supposed to identify the resource you're working with. The key word is IDENTIFY -- i.e. it should be the "unique key" that identifies whatever you are working with -- it should NOT contain all of the "fields of data" that goes with whatever you are working with. The data should be sent in the body, such as with a JSON document (recommended) or XML (today, typically only used for compatability with old software.) But the REST architecture doesn't care what the format of the body is -- just that it is where you transmit the details.
-
- Site Admin
- Posts: 872
- Joined: Sun Jul 04, 2021 5:12 am
Re: How do I tell HTTP Server where "parameters" begin in URI?
In my test, it failed like yours did until I removed the slash from the end of the first part of the ScriptAlias.
so instead of doing this:
I did this:
Then it worked fine. Not sure why you had the extra / there -- were you trying to ensure that a URL of http://server:port/tstconnect did not call your program, and only a url of http://server:port/tstconnect/xxx did?
so instead of doing this:
Code: Select all
ScriptAlias /tstconnect/ /qsys.lib/restful.lib/tstconnect.pgm
Code: Select all
ScriptAlias /tstconnect /qsys.lib/restful.lib/tstconnect.pgm
-
- Posts: 9
- Joined: Thu Jan 05, 2023 8:03 pm
Re: How do I tell HTTP Server where "parameters" begin in URI?
One little slash! No, that was not intentional. Thanks for your help!
-
- Posts: 9
- Joined: Thu Jan 05, 2023 8:03 pm
Re: How do I tell HTTP Server where "parameters" begin in URI?
I have changed my program to receive the filter parameters in a JSON payload rather than passing the filters in the URI.
Now I am having trouble with the STDOUT process. I am not receiving everything that was loaded by the program.
Here is my program:
WHen I run the program in DEBUG and manually set a filter for Item 2692, this is how the DS is loaded.
When I run the program with this DATA-GEN setting...
... this is what the document looks like, which is what I expected.
But when I run the DATA-GEN code to return the results via STDOUT like this...
My resulting doc file only includes these entries.
And this is what is returned in a browser.
Why am I losing the selected Item data?
Now I am having trouble with the STDOUT process. I am not receiving everything that was loaded by the program.
Here is my program:
Code: Select all
**free
/copy qfunctdefn,@copyright
//**************************************************************************************************
// Program : getavlplug
// Description: Get Available Plug Inventory
// Author : Rodney L Gaylor
// Create Date: 07-08-2024
// Notes :
//**************************************************************************************************
// Modifications History
// Date Programmer Name Chg# Description
// ---------- ------------------------- ---- ----------------------------------------------------
// 07-08-2024 Rodney L Gaylor rg00 Program created
//**************************************************************************************************
// Set program control options
ctl-opt dftactgrp(*no)
option(*nodebugio:*srcstmt)
debug(*yes)
bnddir('YAJL');
// Include YAJL procedures
/include yajl_h
// JSON Document data structure for request
dcl-ds jsonrequestdoc qualified;
dcl-ds filters;
item varchar(13) inz('');
size varchar(3) inz('');
desc varchar(40) inz('');
hide ind;
end-ds;
end-ds;
// JSON Document data structure for results returned
dcl-ds jsonresultsdoc qualified;
num_weekdates int(10) inz(0);
dcl-ds weekDates dim(6);
weekdate like(ds_f53weeks.wk00);
end-ds;
num_items int (10) inz(0);
dcl-ds items dim(32767);
item varchar(13) inz('');
size varchar(3) inz('');
desc varchar(40) inz('');
num_weeks int(10) inz(0);
dcl-ds weeks dim(6);
week varchar(10) inz('');
end-ds;
end-ds;
end-ds;
// Program data structures
dcl-ds ds_f53weeks extname('F53WEEKS')
qualified
alias
end-ds;
// Program work fields
dcl-s w_quote char(1) inz('''');
dcl-s w_item varchar(13);
dcl-s w_size varchar(3);
dcl-s w_desc varchar(40);
dcl-s w_wk packed(10);
dcl-s w_wk01 packed(9:2);
dcl-s w_wk02 like(w_wk);
dcl-s w_wk03 like(w_wk);
dcl-s w_wk04 like(w_wk);
dcl-s w_wk05 like(w_wk);
dcl-s w_wk06 like(w_wk);
dcl-s w_pos int(10) inz(0);
dcl-s w_jsonresponse varchar(16000000);
// SQL work fields and constants
dcl-s sql_string varchar(5000);
dcl-c sqlsuccess '00000';
// Program indicators
dcl-s i_where ind inz(*off);
//**************************************************************************************************
// Main Procedure
//**************************************************************************************************
exec sql
set option commit = *none;
// Load week dates for six display columns
exec sql
select *
into :ds_f53weeks
from f53weeks
fetch first row only;
jsonresultsdoc.weekdates(1).weekdate = ds_f53weeks.wk00;
jsonresultsdoc.weekdates(2).weekdate = ds_f53weeks.wk01;
jsonresultsdoc.weekdates(3).weekdate = ds_f53weeks.wk02;
jsonresultsdoc.weekdates(4).weekdate = ds_f53weeks.wk03;
jsonresultsdoc.weekdates(5).weekdate = ds_f53weeks.wk04;
jsonresultsdoc.weekdates(6).weekdate = ds_f53weeks.wk05;
jsonresultsdoc.num_weekdates = 6;
// Retrieve JSON request parameters from *STDIN
monitor;
data-into jsonrequestdoc
%data( '*STDIN' :'case=convert allowmissing=yes')
%parser('YAJLINTO');
on-error;
endmon;
// Build SQL select string from JSON request parameters
sql_string = 'select item, size, description, rb, wk1, wk2, wk3, wk4, wk5 from inv_p00002';
if jsonrequestdoc.filters.item <> *blank;
sql_string += ' where item like '
+ w_quote
+ '%'
+ %trim(jsonrequestdoc.filters.item)
+ '%' + w_quote;
i_where = *on;
endif;
if jsonrequestdoc.filters.size <> *blank;
if not i_where;
sql_string += ' where size like '
+ w_quote
+ '%'
+ %trim(jsonrequestdoc.filters.size)
+ '%'
+ w_quote;
i_where = *on;
else;
sql_string += ' and size like '
+ w_quote
+ '%'
+ %trim(jsonrequestdoc.filters.size)
+ '%' + w_quote;
endif;
endif;
if jsonrequestdoc.filters.desc <> *blank;
if not i_where;
sql_string += ' where description like '
+ w_quote + '%'
+ %trim(jsonrequestdoc.filters.desc)
+ '%'
+ w_quote;
i_where = *on;
else;
sql_string += ' and description like '
+ w_quote
+ '%'
+ %trim(jsonrequestdoc.filters.desc)
+ '%' + w_quote;
endif;
endif;
if jsonrequestdoc.filters.hide = *on;
if not i_where;
sql_string += ' where item not like '
+ w_quote
+ '%P%'
+ w_quote;
i_where = *on;
else;
sql_string += ' and item not like '
+ w_quote
+ '%P%'
+ w_quote;
endif;
endif;
sql_string += ' order by sort, item, size';
// Prepare executable SQL statement p1 from sql_string
exec sql
prepare sql_statement from :sql_string;
// Create sql cursor c1 for items selection
exec sql
declare c1 cursor for sql_statement;
// Open sql cursor
exec sql
open c1;
// Fetch requested item rows from inv_p00002
exec sql
fetch from c1
into :w_item, :w_size, :w_desc, :w_wk01, :w_wk02, :w_wk03, :w_wk04, :w_wk05, :w_wk06;
// Perform jsonResultsDoc data structure load until last item row selected
dow sqlstate = sqlsuccess;
jsonresultsdoc.num_items += 1;
jsonresultsdoc.items(jsonresultsdoc.num_items).item = w_item;
jsonresultsdoc.items(jsonresultsdoc.num_items).size = w_size;
jsonresultsdoc.items(jsonresultsdoc.num_items).desc = w_desc;
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 0;
w_pos = %scan('P' : jsonresultsdoc.items(jsonresultsdoc.num_items).item);
select;
when w_wk01 > 0
and w_pos > 0;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(1).week = %trim(%char(%editc(w_wk01:'3')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 1;
when w_wk01 > 0;
w_wk = w_wk01;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(1).week = %trim(%char(%editc(w_wk:'Z')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 1;
other;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(1).week = *blank;
endsl;
if w_wk02 = 0;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(2).week = *blank;
else;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(2).week = %trim(%char(%editc(w_wk02:'Z')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 2;
endif;
if w_wk03 = 0;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(3).week = *blank;
else;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(3).week = %trim(%char(%editc(w_wk03:'Z')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 3;
endif;
if w_wk04 = 0;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(4).week = *blank;
else;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(4).week = %trim(%char(%editc(w_wk04:'Z')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 4;
endif;
if w_wk05 = 0;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(5).week = *blank;
else;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(5).week = %trim(%char(%editc(w_wk05:'Z')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 5;
endif;
if w_wk06 = 0;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(6).week = *blank;
else;
jsonresultsdoc.items(jsonresultsdoc.num_items).weeks(6).week = %trim(%char(%editc(w_wk06:'Z')));
jsonresultsdoc.items(jsonresultsdoc.num_items).num_weeks = 6;
endif;
exec sql
fetch from c1
into :w_item, :w_size, :w_desc, :w_wk01, :w_wk02, :w_wk03, :w_wk04, :w_wk05, :w_wk06;
enddo;
// Close the c1 sql cursor
exec sql
close c1;
// WHEN I USE THIS CODE I GET THE EXPECTED RESULTS IN THE DOC FILE
//data-gen jsonresultsdoc %data( '/rodneyg/getavlplugresults.json'
// : 'doc=file countprefix=num_'
// ) %gen('YAJLDTAGEN');
// WHEN I USE THIS CODE I DO NOT GET ITEM DATA IN THE DOC FILE OR IN THE STDOUT TO THE BROWSER
// Return requested rows to caller
data-gen jsonresultsdoc %data( '/rodneyg/getavlplugresults.json'
: 'doc=file countprefix=num_'
) %gen('YAJLDTAGEN'
: '{"http status": 200, "write to stdout": true}'
);
*inlr = *on;
return;
Code: Select all
EVAL jsonresultsdoc
JSONRESULTSDOC.NUM_WEEKDATES = 6
JSONRESULTSDOC.WEEKDATES.WEEKDATE(1) = '2024-07-15'
JSONRESULTSDOC.WEEKDATES.WEEKDATE(2) = '2024-07-22'
JSONRESULTSDOC.WEEKDATES.WEEKDATE(3) = '2024-07-29'
JSONRESULTSDOC.WEEKDATES.WEEKDATE(4) = '2024-08-05'
JSONRESULTSDOC.WEEKDATES.WEEKDATE(5) = '2024-08-12'
JSONRESULTSDOC.WEEKDATES.WEEKDATE(6) = '2024-08-19'
JSONRESULTSDOC.NUM_ITEMS = 1
JSONRESULTSDOC.ITEMS.ITEM(1) = '2692 '
JSONRESULTSDOC.ITEMS.SIZE(1) = '50 '
JSONRESULTSDOC.ITEMS.DESC(1) = 'MONTAUK DAISY RC '
JSONRESULTSDOC.ITEMS.NUM_WEEKS(1) = 1
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(1,1) = '3 '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(1,2) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(1,3) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(1,4) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(1,5) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(1,6) = ' '
JSONRESULTSDOC.ITEMS.ITEM(2) = ' '
JSONRESULTSDOC.ITEMS.SIZE(2) = ' '
JSONRESULTSDOC.ITEMS.DESC(2) = ' '
JSONRESULTSDOC.ITEMS.NUM_WEEKS(2) = 0
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(2,1) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(2,2) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(2,3) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(2,4) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(2,5) = ' '
JSONRESULTSDOC.ITEMS.WEEKS.WEEK(2,6) = ' '
Code: Select all
data-gen jsonresultsdoc %data( '/rodneyg/getavlplugresults.json'
: 'doc=file countprefix=num_'
) %gen('YAJLDTAGEN');
Code: Select all
{
"weekDates": [
{
"weekdate": "2024-07-15"
},
{
"weekdate": "2024-07-22"
},
{
"weekdate": "2024-07-29"
},
{
"weekdate": "2024-08-05"
},
{
"weekdate": "2024-08-12"
},
{
"weekdate": "2024-08-19"
}
],
"items": [
{
"item": "2692",
"size": "50",
"desc": "MONTAUK DAISY RC",
"weeks": [
{
"week": "3"
}
]
}
]
}
Code: Select all
data-gen jsonresultsdoc %data( '/rodneyg/getavlplugresults.json'
: 'doc=file countprefix=num_'
) %gen('YAJLDTAGEN'
: '{"http status": 200, "write to stdout": true}'
);
Code: Select all
{
"weekDates": [
{
"weekdate": "2024-07-15"
},
{
"weekdate": "2024-07-22"
},
{
"weekdate": "2024-07-29"
},
{
"weekdate": "2024-08-05"
},
{
"weekdate": "2024-08-12"
},
{
"weekdate": "2024-08-19"
}
]
}
Code: Select all
{"weekDates":[{"weekdate":"2024-07-15"},{"weekdate":"2024-07-22"},{"weekdate":"2024-07-29"},{"weekdate":"2024-08-05"},{"weekdate":"2024-08-12"},{"weekdate":"2024-08-19"}]}
-
- Site Admin
- Posts: 872
- Joined: Sun Jul 04, 2021 5:12 am
Re: How do I tell HTTP Server where "parameters" begin in URI?
I don't see any reason why these would be different. They are running the exact same code under the covers.
Check your num_items field. The results you are reporting are what I would expect if num_items is set to 0.
If you can't figure it out, you'll need to post code that I can use to reproduce the problem. My brain is not a compiler, so posting code and expecting me to figure it out by reading your code isn't really going to work. I can't run the code you've provided, since 99% of it is complex database operations on a database table hat I don't have.
Check your num_items field. The results you are reporting are what I would expect if num_items is set to 0.
If you can't figure it out, you'll need to post code that I can use to reproduce the problem. My brain is not a compiler, so posting code and expecting me to figure it out by reading your code isn't really going to work. I can't run the code you've provided, since 99% of it is complex database operations on a database table hat I don't have.
-
- Posts: 9
- Joined: Thu Jan 05, 2023 8:03 pm
Re: How do I tell HTTP Server where "parameters" begin in URI?
Hi Scott,
I finally got my program working, but now I am having another challenge.
I know this is not a YAJL or HTTPAPI issue, but I have created an HTTP Server, following your guidance in the DIY section of the "Providing Web Services on IBM i" presentation, to run this program as an API. This is my current configuration file for the new HTTP Server. My modifications begin on line 32.
This allows me to execute my program (getavlplug) using the following URI when I am logged in to our network.
I need to make this program available outside our local network to be used on our website. I've been trying to figure out how to do that for three days now, but for the life of me I cannot figure out how to make it available.
Can you help me understand what I need to do to make this server/program available from our public facing domain?
Thanks for any help you can offer!
I finally got my program working, but now I am having another challenge.
I know this is not a YAJL or HTTPAPI issue, but I have created an HTTP Server, following your guidance in the DIY section of the "Providing Web Services on IBM i" presentation, to run this program as an API. This is my current configuration file for the new HTTP Server. My modifications begin on line 32.
Code: Select all
1 # Configuration originally created by Create HTTP Server wizard on Wed Jul 17 12:50:58 EDT 2024
2 Listen *:10020
3 DocumentRoot /www/restserver/htdocs
4 TraceEnable Off
5 Options -FollowSymLinks
6 LogFormat "%h %T %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
7 LogFormat "%{Cookie}n \"%r\" %t" cookie
8 LogFormat "%{User-agent}i" agent
9 LogFormat "%{Referer}i -> %U" referer
10 LogFormat "%h %l %u %t \"%r\" %>s %b" common
11 CustomLog logs/access_log combined
12 LogMaint logs/access_log 7 0
13 LogMaint logs/error_log 7 0
14 SetEnvIf "User-Agent" "Mozilla/2" nokeepalive
15 SetEnvIf "User-Agent" "JDK/1\.0" force-response-1.0
16 SetEnvIf "User-Agent" "Java/1\.0" force-response-1.0
17 SetEnvIf "User-Agent" "RealPlayer 4\.0" force-response-1.0
18 SetEnvIf "User-Agent" "MSIE 4\.0b2;" nokeepalive
19 SetEnvIf "User-Agent" "MSIE 4\.0b2;" force-response-1.0
20 ServerUserID QTMHHTTP
21 <Directory />
22 Require all denied
23 </Directory>
24 <Directory /www/restserver/htdocs>
25 Require all granted
26 </Directory>
27 HTTPSubsystemDesc QHTTPSVR/QHTTPSVR
28 HTTPStartJobDesc QHTTPSVR/QZHBHTTP
29 HTTPStartJobQueue *JOBD
30 HTTPRoutingData *JOBD
31
32 #RESTful web services
33 SetEnv QIBM_CGI_LIBRARY_LIST "RESTFUL;PHPDATA;YAJL"
34 ScriptAliasMatch /rest/([a-z0-9]*) /qsys.lib/restful.lib/$1.pgm
35 <Directory /qsys.lib/restful.lib>
36 Require all granted
37 </Directory>
42 #End RESTful web services
Code: Select all
http://10.151.151.1:10020/rest/getavlplug
Can you help me understand what I need to do to make this server/program available from our public facing domain?
Code: Select all
http://network.kubepak.com (http://96.56.221.220)
-
- Site Admin
- Posts: 872
- Joined: Sun Jul 04, 2021 5:12 am
Re: How do I tell HTTP Server where "parameters" begin in URI?
In order to help you with that, I'd need to be trained in how your network is set up, which type/model of equipment you have and how to use it, and so forth. So this isn't really something I can help with.
I can tell you what the most common setup is...
I can tell you what the most common setup is...
- Your ISP has a line run to your building.
- There is a firewall. It may be built-in to the router (next step) or it might be a separate device. The firewall blocks all traffic unless it is on a list of "open" ports. You'll need to configure it to open a port that goes to your IBM i.
- The line hooks up to a device called a "router". A router's job is to determine what data is going to your network, or from your network, and move it onward to the appropriate place within your network. It will need to be configured so that traffic on a particular port goes to your IBM i. (Or all traffic to a given IP address.)
- Most routers these days use something called Network Address Translation (NAT). You'll know this is involved if you have a separate "internal" and "external" IP address. If you are running NAT, it also needs to be configured to forward the particular port to your IBM i.
- You need to make sure that there are no port retrictions on the IBM i as well.
- You may (and this is a good idea) have a DMZ. This is a setup where there are two firewalls, and the DMZ sits between them (before traffic gets to your internal router). The idea is that the DMZ receives connections to your network and creates a proxy to the IBM i. This way if a hacker breaks in, they only get into the DMZ.