text:
Apache HTTP Server Version 1.3
Apache 1.3Originally written by
URL Rewriting Guide
Ralf S. Engelschall <firstname.lastname@example.com>
December 1997
This document supplements the mod_rewrite reference documentation. It describes how one can use Apache's mod_rewrite to solve typical URL-based problems webmasters are usually confronted with in practice. I give detailed descriptions on how to solve each problem by configuring URL rewriting rulesets.
Introduction to mod_rewriteThe Apache module mod_rewrite is a killer one, i.e. it is a really sophisticated module which provides a powerful way to do URL manipulations. With it you can nearly do all types of URL manipulations you ever dreamed about. The price you have to pay is to accept complexity, because mod_rewrite's major drawback is that it is not easy to understand and use for the beginner. And even Apache experts sometimes discover new aspects where mod_rewrite can help.
In other words: With mod_rewrite you either shoot yourself in the foot the first time and never use it again or love it for the rest of your life because of its power. This paper tries to give you a few initial success events to avoid the first case by presenting already invented solutions to you.
Practical SolutionsHere come a lot of practical solutions I've either invented myself or collected from other peoples solutions in the past. Feel free to learn the black magic of URL rewriting from these examples.
ATTENTION: Depending on your server-configuration it can be necessary to slightly change the examples for your situation, e.g. adding the [PT] flag when additionally using mod_alias and mod_userdir, etc. Or rewriting a ruleset to fit in
.htaccesscontext instead of per-server context. Always try to understand what a particular ruleset really does before you use it. It avoid problems.
URL Layout
Canonical URLs
- Description:
- On some webservers there are more than one URL for a resource. Usually there are canonical URLs (which should be actually used and distributed) and those which are just shortcuts, internal ones, etc. Independent which URL the user supplied with the request he should finally see the canonical one only.
- Solution:
- We do an external HTTP redirect for all non-canonical URLs to fix them in the location view of the Browser and for all subsequent requests. In the example ruleset below we replace
/~userby the canonical
/u/userand fix a missing trailing slash for
RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R] RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]
Canonical Hostnames
- Description:
- ...
- Solution:
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] RewriteCond %{HTTP_HOST} !^$ RewriteCond %{SERVER_PORT} !^80$ RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R] RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] RewriteCond %{HTTP_HOST} !^$ RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]
Moved DocumentRoot
- Description:
- Usually the DocumentRoot of the webserver directly relates to the URL ``
/''. But often this data is not really of top-level priority, it is perhaps just one entity of a lot of data pools. For instance at our Intranet sites there are
/e/www/(the homepage for WWW),
/e/sww/(the homepage for the Intranet) etc. Now because the data of the DocumentRoot stays at
/e/www/we had to make sure that all inlined images and other stuff inside this data pool work for subsequent requests.
- Solution:
- We just redirect the URL
/e/www/. While is seems trivial it is actually trivial with mod_rewrite, only. Because the typical old mechanisms of URL Aliases (as provides by mod_alias and friends) only used prefix matching. With this you cannot do such a redirection because the DocumentRoot is a prefix of all URLs. With mod_rewrite it is really trivial:
RewriteEngine on RewriteRule ^/$ /e/www/ [R]
Trailing Slash Problem
- Description:
- Every webmaster can sing a song about the problem of the trailing slash on URLs referencing directories. If they are missing, the server dumps an error, because if you say
/~quux/fooinstead of
/~quux/foo/then the server searches for a file named
foo. And because this file is a directory it complains. Actually is tries to fix it themself in most of the cases, but sometimes this mechanism need to be emulated by you. For instance after you have done a lot of complicated URL rewritings to CGI scripts etc.
- Solution:
- The solution to this subtle problem is to let the server add the trailing slash automatically. To do this correctly we have to use an external redirect, so the browser correctly requests subsequent images etc. If we only did a internal rewrite, this would only work for the directory page, but would go wrong when any images are included into this page with relative URLs, because the browser would request an in-lined object. For instance, a request for
/~quux/foo/index.htmlwould become
/~quux/image.gifwithout the external redirect!
So, to do this trick we write:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo$ foo/ [R]
The crazy and lazy can even do the following in the top-level
.htaccessfile of their homedir. But notice that this creates some processing overhead.
RewriteEngine on RewriteBase /~quux/ RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^(.+[^/])$ $1/ [R]
Webcluster through Homogeneous URL Layout
- Description:
- We want to create a homogenous and consistent URL layout over all WWW servers on a Intranet webcluster, i.e. all URLs (per definition server local and thus server dependent!) become actually server independed! What we want is to give the WWW namespace a consistent server-independend layout: no URL should have to include any physically correct target server. The cluster itself should drive us automatically to the physical target host.
- Solution:
- First, the knowledge of the target servers come from (distributed) external maps which contain information where our users, groups and entities stay. The have the formuser1 server_of_user1 user2 server_of_user2 : :
We put them into files
map.xxx-to-host. Second we need to instruct all servers to redirect URLs of the forms/u/user/anypath /g/group/anypath /e/entity/anypath
tohttp://physical-host/u/user/anypath http://physical-host/g/group/anypath http://physical-host/e/entity/anypath
when the URL is not locally valid to a server. The following ruleset does this for us by the help of the map files (assuming that server0 is a default server which will be used if a user has no entry in the map):
RewriteEngine on RewriteMap user-to-host txt:/path/to/map.user-to-host RewriteMap group-to-host txt:/path/to/map.group-to-host RewriteMap entity-to-host txt:/path/to/map.entity-to-host RewriteRule ^/u/([^/]+)/?(.*) http://${user-to-host:$1|server0}/u/$1/$2 RewriteRule ^/g/([^/]+)/?(.*) http://${group-to-host:$1|server0}/g/$1/$2 RewriteRule ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2 RewriteRule ^/([uge])/([^/]+)/?$ /$1/$2/.www/ RewriteRule ^/([uge])/([^/]+)/([^.]+.+) /$1/$2/.www/$3\
Move Homedirs to Different Webserver
- Description:
- A lot of webmaster aksed for a solution to the following situation: They wanted to redirect just all homedirs on a webserver to another webserver. They usually need such things when establishing a newer webserver which will replace the old one over time.
- Solution:
- The solution is trivial with mod_rewrite. On the old webserver we just redirect all
/~user/anypathURLs to
RewriteEngine on RewriteRule ^/~(.+) http://newserver/~$1 [R,L]
Structured Homedirs
- Description:
- Some sites with thousend of users usually use a structured homedir layout, i.e. each homedir is in a subdirectory which begins for instance with the first character of the username. So,
- Solution:
- We use the following ruleset to expand the tilde URLs into exactly the above layout.
RewriteEngine on RewriteRule ^/~(([a-z])[a-z0-9]+)(.*) /home/$2/$1/.www$3
Filesystem Reorganisation
- Description:
- This really is a hardcore example: a killer application which heavily uses per-directory
RewriteRulesto get a smooth look and feel on the Web while its data structure is never touched or adjusted. Background: net.sw is my archive of freely available Unix software packages, which I started to collect in 1992. It is both my hobby and job to to this, because while I'm studying computer science I have also worked for many years as a system and network administrator in my spare time. Every week I need some sort of software so I created a deep hierarchy of directories where I stored the packages:drwxrwxr-x 2 netsw users 512 Aug 3 18:39 Audio/ drwxrwxr-x 2 netsw users 512 Jul 9 14:37 Benchmark/ drwxrwxr-x 12 netsw users 512 Jul 9 00:34 Crypto/ drwxrwxr-x 5 netsw users 512 Jul 9 00:41 Database/ drwxrwxr-x 4 netsw users 512 Jul 30 19:25 Dicts/ drwxrwxr-x 10 netsw users 512 Jul 9 01:54 Graphic/ drwxrwxr-x 5 netsw users 512 Jul 9 01:58 Hackers/ drwxrwxr-x 8 netsw users 512 Jul 9 03:19 InfoSys/ drwxrwxr-x 3 netsw users 512 Jul 9 03:21 Math/ drwxrwxr-x 3 netsw users 512 Jul 9 03:24 Misc/ drwxrwxr-x 9 netsw users 512 Aug 1 16:33 Network/ drwxrwxr-x 2 netsw users 512 Jul 9 05:53 Office/ drwxrwxr-x 7 netsw users 512 Jul 9 09:24 SoftEng/ drwxrwxr-x 7 netsw users 512 Jul 9 12:17 System/ drwxrwxr-x 12 netsw users 512 Aug 3 20:15 Typesetting/ drwxrwxr-x 10 netsw users 512 Jul 9 14:08 X11/
In July 1996 I decided to make this archive public to the world via a nice Web interface. "Nice" means that I wanted to offer an interface where you can browse directly through the archive hierarchy. And "nice" means that I didn't wanted to change anything inside this hierarchy - not even by putting some CGI scripts at the top of it. Why? Because the above structure should be later accessible via FTP as well, and I didn't want any Web or CGI stuff to be there.
- Solution:
- The solution has two parts: The first is a set of CGI scripts which create all the pages at all directory levels on-the-fly. I put them under
/e/netsw/.www/as follows:-rw-r--r-- 1 netsw users 1318 Aug 1 18:10 .wwwacl drwxr-xr-x 18 netsw users 512 Aug 5 15:51 DATA/ -rw-rw-rw- 1 netsw users 372982 Aug 5 16:35 LOGFILE -rw-r--r-- 1 netsw users 659 Aug 4 09:27 TODO -rw-r--r-- 1 netsw users 5697 Aug 1 18:01 netsw-about.html -rwxr-xr-x 1 netsw users 579 Aug 2 10:33 netsw-access.pl -rwxr-xr-x 1 netsw users 1532 Aug 1 17:35 netsw-changes.cgi -rwxr-xr-x 1 netsw users 2866 Aug 5 14:49 netsw-home.cgi drwxr-xr-x 2 netsw users 512 Jul 8 23:47 netsw-img/ -rwxr-xr-x 1 netsw users 24050 Aug 5 15:49 netsw-lsdir.cgi -rwxr-xr-x 1 netsw users 1589 Aug 3 18:43 netsw-search.cgi -rwxr-xr-x 1 netsw users 1885 Aug 1 17:41 netsw-tree.cgi -rw-r--r-- 1 netsw users 234 Jul 30 16:35 netsw-unlimit.lst
DATA/subdirectory holds the above directory structure, i.e. the real net.sw stuff and gets automatically updated via
rdistfrom time to time. The second part of the problem remains: how to link these two structures together into one smooth-looking URL tree? We want to hide the
DATA/directory from the user while running the appropriate CGI scripts for the various URLs. Here is the solution: first I put the following into the per-directory configuration file in the Document Root of the server to rewrite the announced URL
/net.sw/to the internal path
RewriteRule ^net.sw$ net.sw/ [R] RewriteRule ^net.sw/(.*)$ e/netsw/$1
The first rule is for requests which miss the trailing slash! The second rule does the real thing. And then comes the killer configuration which stays in the per-directory config file
Options ExecCGI FollowSymLinks Includes MultiViews RewriteEngine on # we are reached via /net.sw/ prefix RewriteBase /net.sw/ # first we rewrite the root dir to # the handling cgi script RewriteRule ^$ netsw-home.cgi [L] RewriteRule ^index\.html$ netsw-home.cgi [L] # strip out the subdirs when # the browser requests us from perdir pages RewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L] # and now break the rewriting for local files RewriteRule ^netsw-home\.cgi.* - [L] RewriteRule ^netsw-changes\.cgi.* - [L] RewriteRule ^netsw-search\.cgi.* - [L] RewriteRule ^netsw-tree\.cgi$ - [L] RewriteRule ^netsw-about\.html$ - [L] RewriteRule ^netsw-img/.*$ - [L] # anything else is a subdir which gets handled # by another cgi script RewriteRule !^netsw-lsdir\.cgi.* - [C] RewriteRule (.*) netsw-lsdir.cgi/$1
Some hints for interpretation:
- Notice the L (last) flag and no substitution field ('-') in the forth part
- Notice the ! (not) character and the C (chain) flag at the first rule in the last part
- Notice the catch-all pattern in the last rule
NCSA imagemap to Apache mod_imap
- Description:
- When switching from the NCSA webserver to the more modern Apache webserver a lot of people want a smooth transition. So they want pages which use their old NCSA
imagemapprogram to work under Apache with the modern
mod_imap. The problem is that there are a lot of hyperlinks around which reference the
imagemapprogram via
/cgi-bin/imagemap/path/to/page.map. Under Apache this has to read just
- Solution:
- We use a global rule to remove the prefix on-the-fly for all requests:
RewriteEngine on RewriteRule ^/cgi-bin/imagemap(.*) $1 [PT]
Search pages in more than one directory
- Description:
- Sometimes it is neccessary to let the webserver search for pages in more than one directory. Here MultiViews or other techniques cannot help.
- Solution:
- We program a explicit ruleset which searches for the files in the directories.
RewriteEngine on # first try to find it in custom/... # ...and if found stop and be happy: RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f RewriteRule ^(.+) /your/docroot/dir1/$1 [L] # second try to find it in pub/... # ...and if found stop and be happy: RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f RewriteRule ^(.+) /your/docroot/dir2/$1 [L] # else go on for other Alias or ScriptAlias directives, # etc. RewriteRule ^(.+) - [PT]
Set Environment Variables According To URL Parts
- Description:
- Perhaps you want to keep status information between requests and use the URL to encode it. But you don't want to use a CGI wrapper for all pages just to strip out this information.
- Solution:
- We use a rewrite rule to strip out the status information and remember it via an environment variable which can be later dereferenced from within XSSI or CGI. This way a URL
/foo/S=java/bar/gets translated to
/foo/bar/and the environment variable named
STATUSis set to the value "java".
RewriteEngine on RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]
Virtual User Hosts
- Description:
- Assume that you want to provide
www.username.host.domain.comfor the homepage of username via just DNS A records to the same machine and without any virtualhosts on this machine.
- Solution:
- For HTTP/1.0 requests there is no solution, but for HTTP/1.1 requests which contain a Host: HTTP header we can use the following ruleset to rewrite
http://www.username.host.com/anypathinternally to
RewriteEngine on RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$ RewriteRule ^(.+) %{HTTP_HOST}$1 [C] RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2
Redirect Homedirs For Foreigners
- Description:
- We want to redirect homedir URLs to another webserver
www.somewhere.comwhen the requesting user does not stay in the local domain
ourdomain.com. This is sometimes used in virtual host contexts.
- Solution:
- Just a rewrite condition:
RewriteEngine on RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$ RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]
Redirect Failing URLs To Other Webserver
- Description:
- A typical FAQ about URL rewriting is how to redirect failing requests on webserver A to webserver B. Usually this is done via ErrorDocument CGI-scripts in Perl, but there is also a mod_rewrite solution. But notice that this is less performant than using a ErrorDocument CGI-script!
- Solution:
- The first solution has the best performance but less flexibility and is less error safe:
RewriteEngine on RewriteCond /your/docroot/%{REQUEST_FILENAME} !-f RewriteRule ^(.+) http://webserverB.dom/$1
The problem here is that this will only work for pages inside the DocumentRoot. While you can add more Conditions (for instance to also handle homedirs, etc.) there is better variant:
RewriteEngine on RewriteCond %{REQUEST_URI} !-U RewriteRule ^(.+) http://webserverB.dom/$1
This uses the URL look-ahead feature of mod_rewrite. The result is that this will work for all types of URLs and is a safe way. But it does a performance impact on the webserver, because for every request there is one more internal subrequest. So, if your webserver runs on a powerful CPU, use this one. If it is a slow machine, use the first approach or better a ErrorDocument CGI-script.
Extended Redirection
- Description:
- Sometimes we need more control (concerning the character escaping mechanism) of URLs on redirects. Usually the Apache kernels URL escape function also escapes anchors, i.e. URLs like "url#anchor". You cannot use this directly on redirects with mod_rewrite because the uri_escape() function of Apache would also escape the hash character. How can we redirect to such a URL?
- Solution:
- We have to use a kludge by the use of a NPH-CGI script which does the redirect itself. Because here no escaping is done (NPH=non-parseable headers). First we introduce a new URL scheme
xredirect:by the following per-server config-line (should be one of the last rewrite rules):
RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \ [T=application/x-httpd-cgi,L]
This forces all URLs prefixed with
xredirect:to be piped through the
nph-xredirect.cgiprogram. And this program just looks like:
#!/path/to/perl ## ## nph-xredirect.cgi -- NPH/CGI script for extended redirects ## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. ## $| = 1; $url = $ENV{'PATH_INFO'}; print "HTTP/1.0 302 Moved Temporarily\n"; print "Server: $ENV{'SERVER_SOFTWARE'}\n"; print "Location: $url\n"; print "Content-type: text/html\n"; print "\n"; print "\n"; print "\n"; print "<title>302 Moved Temporarily (EXTENDED)</title>\n"; print "\n"; print "\n"; print "
Moved Temporarily (EXTENDED)
\n"; print "The document has moved here.
\n"; print "\n"; print "\n"; ##EOF##
This provides you with the functionality to do redirects to all URL schemes, i.e. including the one which are not directly accepted by mod_rewrite. For instance you can now also redirect to
RewriteRule ^anyurl xredirect:news:newsgroup
Notice: You have not to put [R] or [R,L] to the above rule because the
xredirect:need to be expanded later by our special "pipe through" rule above.
Archive Access Multiplexer
- Description:
- Do you know the great CPAN (Comprehensive Perl Archive Network) under http://www.perl.com/CPAN? This does a redirect to one of several FTP servers around the world which carry a CPAN mirror and is approximately near the location of the requesting client. Actually this can be called an FTP access multiplexing service. While CPAN runs via CGI scripts, how can a similar approach implemented via mod_rewrite?
- Solution:
- First we notice that from version 3.0.0 mod_rewrite can also use the "ftp:" scheme on redirects. And second, the location approximation can be done by a rewritemap over the top-level domain of the client. With a tricky chained ruleset we can use this top-level domain as a key to our multiplexing map.
RewriteEngine on RewriteMap multiplex txt:/path/to/map.cxan RewriteRule ^/CxAN/(.*) %{REMOTE_HOST}::$1 [C] RewriteRule ^.+\.([a-zA-Z]+)::(.*)$ ${multiplex:$1|ftp.default.dom}$2 [R,L]
## ## map.cxan -- Multiplexing Map for CxAN ## de ftp://ftp.cxan.de/CxAN/ uk ftp://ftp.cxan.uk/CxAN/ com ftp://ftp.cxan.com/CxAN/ : ##EOF##
Time-Dependend Rewriting
- Description:
- When tricks like time-dependend content should happen a lot of webmasters still use CGI scripts which do for instance redirects to specialized pages. How can it be done via mod_rewrite?
- Solution:
- There are a lot of variables named
TIME_xxxfor rewrite conditions. In conjunction with the special lexicographic comparison patterns <STRING, >STRING and =STRING we can do time-dependend redirects:
RewriteEngine on RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 RewriteRule ^foo\.html$ foo.day.html RewriteRule ^foo\.html$ foo.night.html
This provides the content of
foo.day.htmlunder the URL
foo.htmlfrom 07:00-19:00 and at the remaining time the contents of
foo.night.html. Just a nice feature for a homepage...
Backward Compatibility for YYYY to XXXX migration
- Description:
- How can we make URLs backward compatible (still existing virtually) after migrating document.YYYY to document.XXXX, e.g. after translating a bunch of .html files to .phtml?
- Solution:
- We just rewrite the name to its basename and test for existence of the new extension. If it exists, we take that name, else we rewrite the URL to its original state.
# backward compatibility ruleset for # rewriting document.html to document.phtml # when and only when document.phtml exists # but no longer document.html RewriteEngine on RewriteBase /~quux/ # parse out basename, but remember the fact RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes] # rewrite to document.phtml if exists RewriteCond %{REQUEST_FILENAME}.phtml -f RewriteRule ^(.*)$ $1.phtml [S=1] # else reverse the previous basename cutout RewriteCond %{ENV:WasHTML} ^yes$ RewriteRule ^(.*)$ $1.html
Content Handling
From Old to New (intern)
- Description:
- Assume we have recently renamed the page
foo.htmland now want to provide the old URL for backward compatibility. Actually we want that users of the old URL even not recognize that the pages was renamed.
- Solution:
- We rewrite the old URL to the new one internally via the following rule:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ bar.html
From Old to New (extern)
- Description:
- Assume again that we have recently renamed the page
foo.htmland now want to provide the old URL for backward compatibility. But this time we want that the users of the old URL get hinted to the new one, i.e. their browsers Location field should change, too.
- Solution:
- We force a HTTP redirect to the new URL which leads to a change of the browsers and thus the users view:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ bar.html [R]
Browser Dependend Content
- Description:
- At least for important top-level pages it is sometimes necesarry to provide the optimum of browser dependend content, i.e. one has to provide a maximum version for the latest Netscape variants, a minimum version for the Lynx browsers and a average feature version for all others.
- Solution:
- We cannot use content negotiation because the browsers do not provide their type in that form. Instead we have to act on the HTTP header "User-Agent". The following condig does the following: If the HTTP header "User-Agent" begins with "Mozilla/3", the page
foo.htmlis rewritten to
foo.NS.htmland and the rewriting stops. If the browser is "Lynx" or "Mozilla" of version 1 or 2 the URL becomes
foo.20.html. All other browsers receive page
foo.32.html. This is done by the following ruleset:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/3.* RewriteRule ^foo\.html$ foo.NS.html [L] RewriteCond %{HTTP_USER_AGENT} ^Lynx/.* [OR] RewriteCond %{HTTP_USER_AGENT} ^Mozilla/[12].* RewriteRule ^foo\.html$ foo.20.html [L] RewriteRule ^foo\.html$ foo.32.html [L]
Dynamic Mirror
- Description:
- Assume there are nice webpages on remote hosts we want to bring into our namespace. For FTP servers we would use the
mirrorprogram which actually maintains an explicit up-to-date copy of the remote data on the local machine. For a webserver we could use the program
webcopywhich acts similar via HTTP. But both techniques have one major drawback: The local copy is always just as up-to-date as often we run the program. It would be much better if the mirror is not a static one we have to establish explicitly. Instead we want a dynamic mirror with data which gets updated automatically when there is need (updated data on the remote host).
- Solution:
- To provide this feature we map the remote webpage or even the complete remote webarea to our namespace by the use of the Proxy Throughput feature (flag [P]):
RewriteEngine on RewriteBase /~quux/ RewriteRule ^hotsheet/(.*)$ http://www.tstimpreso.com/hotsheet/$1 [P]
RewriteEngine on RewriteBase /~quux/ RewriteRule ^usa-news\.html$ http://www.quux-corp.com/news/index.html [P]
Reverse Dynamic Mirror
- Description:
- ...
- Solution:
RewriteEngine on RewriteCond /mirror/of/remotesite/$1 -U RewriteRule ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1
Retrieve Missing Data from Intranet
- Description:
- This is a tricky way of virtually running a corporates (external) Internet webserver (
www.quux-corp.dom), while actually keeping and maintaining its data on a (internal) Intranet webserver (
www2.quux-corp.dom) which is protected by a firewall. The trick is that on the external webserver we retrieve the requested data on-the-fly from the internal one.
- Solution:
- First, we have to make sure that our firewall still protects the internal webserver and that only the external webserver is allowed to retrieve data from it. For a packet-filtering firewall we could for instance configure a firewall ruleset like the following:
ALLOW Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port 80 DENY Host * Port * --> Host www2.quux-corp.dom Port 80
Just adjust it to your actual configuration syntax. Now we can establish the mod_rewrite rules which request the missing data in the background through the proxy throughput feature:
RewriteRule ^/~([^/]+)/?(.*) /home/$1/.www/$2 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^/home/([^/]+)/.www/?(.*) http://www2.quux-corp.dom/~$1/pub/$2 [P]
Load Balancing
- Description:
- Suppose we want to load balance the traffic to
www[0-5].foo.com(a total of 6 servers). How can this be done?
- Solution:
- There are a lot of possible solutions for this problem. We will discuss first a commonly known DNS-based variant and then the special one with mod_rewrite:
- DNS Round-Robin
The simplest method for load-balancing is to use the DNS round-robin feature of BIND. Here you just configure
www[0-9].foo.comas usual in your DNS with A(address) records, e.g.
www0 IN A 22.214.171.124 www1 IN A 126.96.36.199 www2 IN A 220.127.116.11 www3 IN A 18.104.22.168 www4 IN A 22.214.171.124 www5 IN A 22.214.171.124
Then you additionally add the following entry:
www IN CNAME www0.foo.com. IN CNAME www1.foo.com. IN CNAME www2.foo.com. IN CNAME www3.foo.com. IN CNAME www4.foo.com. IN CNAME www5.foo.com. IN CNAME www6.foo.com.
Notice that this seems wrong, but is actually an intended feature of BIND and can be used in this way. However, now when
www.foo.comgets resolved, BIND gives out
www0-www6- but in a slightly permutated/rotated order every time. This way the clients are spread over the various servers. But notice that this not a perfect load balancing scheme, because DNS resolve information gets cached by the other nameservers on the net, so once a client has resolved
www.foo.comto a particular
wwwN.foo.com, all subsequent requests also go to this particular name
wwwN.foo.com. But the final result is ok, because the total sum of the requests are really spread over the various webservers.
- DNS Load-Balancing
A sophisticated DNS-based method for load-balancing is to use the program
lbnamedwhich can be found at http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html. It is a Perl 5 program in conjunction with auxilliary tools which provides a real load-balancing for DNS.
- Proxy Throughput Round-Robin
In this variant we use mod_rewrite and its proxy throughput feature. First we dedicate
www0.foo.comto be actually
www.foo.comby using a single
www IN CNAME www0.foo.com.
entry in the DNS. Then we convert
www0.foo.comto a proxy-only server, i.e. we configure this machine so all arriving URLs are just pushed through the internal proxy to one of the 5 other servers (
www1-www5). To accomplish this we first establish a ruleset which contacts a load balancing script
lb.plfor all URLs.
RewriteEngine on RewriteMap lb prg:/path/to/lb.pl RewriteRule ^/(.+)$ ${lb:$1} [P,L]
Then we write
#!/path/to/perl ## ## lb.pl -- load balancing script ## $| = 1; $name = "www"; # the hostname base $first = 1; # the first server (not 0 here, because 0 is myself) $last = 5; # the last server in the round-robin $domain = "foo.dom"; # the domainname $cnt = 0; while (<STDIN>) { $cnt = (($cnt+1) % ($last+1-$first)); $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain); print "http://$server/$_"; } ##EOF##
A last notice: Why is this useful? Seems like
www0.foo.comstill is overloaded? The answer is yes, it is overloaded, but with plain proxy throughput requests, only! All SSI, CGI, ePerl, etc. processing is completely done on the other machines. This is the essential point.
- Hardware/TCP Round-Robin
There is a hardware solution available, too. Cisco has a beast called LocalDirector which does a load balancing at the TCP/IP level. Actually this is some sort of a circuit level gateway in front of a webcluster. If you have enough money and really need a solution with high performance, use this one.
Reverse Proxy
- Description:
- ...
- Solution:
## ## apache-rproxy.conf -- Apache configuration for Reverse Proxy Usage ## # server type ServerType standalone Port 8000 MinSpareServers 16 StartServers 16 MaxSpareServers 16 MaxClients 16 MaxRequestsPerChild 100 # server operation parameters KeepAlive on MaxKeepAliveRequests 100 KeepAliveTimeout 15 Timeout 400 IdentityCheck off HostnameLookups off # paths to runtime files PidFile /path/to/apache-rproxy.pid LockFile /path/to/apache-rproxy.lock ErrorLog /path/to/apache-rproxy.elog CustomLog /path/to/apache-rproxy.dlog "%{%v/%T}t %h -> %{SERVER}e URL: %U" # unused paths ServerRoot /tmp DocumentRoot /tmp CacheRoot /tmp RewriteLog /dev/null TransferLog /dev/null TypesConfig /dev/null AccessConfig /dev/null ResourceConfig /dev/null # speed up and secure processing <Directory /> Options -FollowSymLinks -SymLinksIfOwnerMatch AllowOverride None </Directory> # the status page for monitoring the reverse proxy <Location /apache-rproxy-status> SetHandler server-status </Location> # enable the URL rewriting engine RewriteEngine on RewriteLogLevel 0 # define a rewriting map with value-lists where # mod_rewrite randomly chooses a particular value RewriteMap server rnd:/path/to/apache-rproxy.conf-servers # make sure the status page is handled locally # and make sure no one uses our proxy except ourself RewriteRule ^/apache-rproxy-status.* - [L] RewriteRule ^(http|ftp)://.* - [F] # now choose the possible servers for particular URL types RewriteRule ^/(.*\.(cgi|shtml))$ to://${server:dynamic}/$1 [S=1] RewriteRule ^/(.*)$ to://${server:static}/$1 # and delegate the generated URL by passing it # through the proxy module RewriteRule ^to://([^/]+)/(.*) http://$1/$2 [E=SERVER:$1,P,L] # and make really sure all other stuff is forbidden # when it should survive the above rules... RewriteRule .* - [F] # enable the Proxy module without caching ProxyRequests on NoCache * # setup URL reverse mapping for redirect reponses ProxyPassReverse / http://www1.foo.dom/ ProxyPassReverse / http://www2.foo.dom/ ProxyPassReverse / http://www3.foo.dom/ ProxyPassReverse / http://www4.foo.dom/ ProxyPassReverse / http://www5.foo.dom/ ProxyPassReverse / http://www6.foo.dom/
## ## apache-rproxy.conf-servers -- Apache/mod_rewrite selection table ## # list of backend servers which serve static # pages (HTML files and Images, etc.) static www1.foo.dom|www2.foo.dom|www3.foo.dom|www4.foo.dom # list of backend servers which serve dynamically # generated page (CGI programs or mod_perl scripts) dynamic www5.foo.dom|www6.foo.dom
New MIME-type, New Service
- Description:
- On the net there are a lot of nifty CGI programs. But their usage is usually boring, so a lot of webmaster don't use them. Even Apache's Action handler feature for MIME-types is only appropriate when the CGI programs don't need special URLs (actually PATH_INFO and QUERY_STRINGS) as their input. First, let us configure a new file type with extension
.scgi(for secure CGI) which will be processed by the popular
cgiwrapprogram. The problem here is that for instance we use a Homogeneous URL Layout (see above) a file inside the user homedirs has the URL
/u/user/foo/bar.scgi. But
cgiwrapneeds the URL in the form
/~user/foo/bar.scgi/. The following rule solves the problem:
RewriteRule ^/[uge]/([^/]+)/\.www/(.+)\.scgi(.*) ... ... /internal/cgi/user/cgiwrap/~$1/$2.scgi$3 [NS,T=application/x-http-cgi]
Or assume we have some more nifty programs:
wwwlog(which displays the
access.logfor a URL subtree and
wwwidx(which runs Glimpse on a URL subtree). We have to provide the URL area to these programs so they know on which area they have to act on. But usually this ugly, because they are all the times still requested from that areas, i.e. typically we would run the
swwidxprogram from within
/u/user/foo/via hyperlink to/internal/cgi/user/swwidx?i=/u/user/foo/
which is ugly. Because we have to hard-code both the location of the area and the location of the CGI inside the hyperlink. When we have to reorganise or area, we spend a lot of time changing the various hyperlinks.
- Solution:
- The solution here is to provide a special new URL format which automatically leads to the proper CGI invocation. We configure the following:
RewriteRule ^/([uge])/([^/]+)(/?.*)/\* /internal/cgi/user/wwwidx?i=/$1/$2$3/ RewriteRule ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3
Now the hyperlink to search at
/u/user/foo/reads onlyHREF="*"
which internally gets automatically transformed to/internal/cgi/user/wwwidx?i=/u/user/foo/
The same approach leads to an invocation for the access log CGI program when the hyperlink
:loggets used.
From Static to Dynamic
- Description:
- How can we transform a static page
foo.htmlinto a dynamic variant
foo.cgiin a seemless way, i.e. without notice by the browser/user.
- Solution:
- We just rewrite the URL to the CGI-script and force the correct MIME-type so it gets really run as a CGI-script. This way a request to
/~quux/foo.htmlinternally leads to the invokation of
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]
On-the-fly Content-Regeneration
- Description:
- Here comes a really esoteric feature: Dynamically generated but statically served pages, i.e. pages should be delivered as pure static pages (read from the filesystem and just passed through), but they have to be generated dynamically by the webserver if missing. This way you can have CGI-generated pages which are statically served unless one (or a cronjob) removes the static contents. Then the contents gets refreshed.
- Solution:
- This is done via the following ruleset:
RewriteCond %{REQUEST_FILENAME} !-s RewriteRule ^page\.html$ page.cgi [T=application/x-httpd-cgi,L]
Here a request to
page.htmlleads to a internal run of a corresponding
page.htmlis still missing or has filesize null. The trick here is that
page.cgiis a usual CGI script which (additionally to its STDOUT) writes its output to the file
page.html. Once it was run, the server sends out the data of
page.html. When the webmaster wants to force a refresh the contents, he just removes
page.html(usually done by a cronjob).
Document With Autorefresh
- Description:
- Wouldn't it be nice while creating a complex webpage if the webbrowser would automatically refresh the page every time we write a new version from within our editor? Impossible?
- Solution:
- No! We just combine the MIME multipart feature, the webserver NPH feature and the URL manipulation power of mod_rewrite. First, we establish a new URL feature: Adding just
:refreshto any URL causes this to be refreshed every time it gets updated on the filesystem.
RewriteRule ^(/[uge]/[^/]+/?.*):refresh /internal/cgi/apache/nph-refresh?f=$1
Now when we reference the URL/u/foo/bar/page.html:refresh
this leads to the internal invocation of the URL/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
The only missing part is the NPH-CGI script. Although one would usually say "left as an exercise to the reader" ;-) I will provide this, too.#!/sw/bin/perl ## ## nph-refresh -- NPH/CGI script for auto refreshing pages ## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. ## $| = 1; # split the QUERY_STRING variable @pairs = split(/&/, $ENV{'QUERY_STRING'}); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $name =~ tr/A-Z/a-z/; $name = 'QS_' . $name; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; eval "\$$name = \"$value\""; } $QS_s = 1 if ($QS_s eq ''); $QS_n = 3600 if ($QS_n eq ''); if ($QS_f eq '') { print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n\n"; print "ERROR: No file given\n"; exit(0); } if (! -f $QS_f) { print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n\n"; print "ERROR: File $QS_f not found\n"; exit(0); } sub print_http_headers_multipart_begin { print "HTTP/1.0 200 OK\n"; $bound = "ThisRandomString12345"; print "Content-type: multipart/x-mixed-replace;boundary=$bound\n"; &print_http_headers_multipart_next; } sub print_http_headers_multipart_next { print "\n--$bound\n"; } sub print_http_headers_multipart_end { print "\n--$bound--\n"; } sub displayhtml { local($buffer) = @_; $len = length($buffer); print "Content-type: text/html\n"; print "Content-length: $len\n\n"; print $buffer; } sub readfile { local($file) = @_; local(*FP, $size, $buffer, $bytes); ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file); $size = sprintf("%d", $size); open(FP, "<$file"); $bytes = sysread(FP, $buffer, $size); close(FP); return $buffer; } $buffer = &readfile($QS_f); &print_http_headers_multipart_begin; &displayhtml($buffer); sub mystat { local($file) = $_[0]; local($time); ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file); return $mtime; } $mtimeL = &mystat($QS_f); $mtime = $mtime; for ($n = 0; $n < $QS_n; $n++) { while (1) { $mtime = &mystat($QS_f); if ($mtime ne $mtimeL) { $mtimeL = $mtime; sleep(2); $buffer = &readfile($QS_f); &print_http_headers_multipart_next; &displayhtml($buffer); sleep(5); $mtimeL = &mystat($QS_f); last; } sleep($QS_s); } } &print_http_headers_multipart_end; exit(0); ##EOF##
Mass Virtual Hosting
- Description:
- The
<VirtualHost>feature of Apache is nice and works great when you just have a few dozens virtual hosts. But when you are an ISP and have hundreds of virtual hosts to provide this feature is not the best choice.
- Solution:
- To provide this feature we map the remote webpage or even the complete remote webarea to our namespace by the use of the Proxy Throughput feature (flag [P]):
## ## vhost.map ## www.vhost1.dom:80 /path/to/docroot/vhost1 www.vhost2.dom:80 /path/to/docroot/vhost2 : www.vhostN.dom:80 /path/to/docroot/vhostN
## ## httpd.conf ## : # use the canonical hostname on redirects, etc. UseCanonicalName on : # add the virtual host in front of the CLF-format CustomLog /path/to/access_log "%{VHOST}e %h %l %u %t \"%r\" %>s %b" : # enable the rewriting engine in the main server RewriteEngine on # define two maps: one for fixing the URL and one which defines # the available virtual hosts with their corresponding # DocumentRoot. RewriteMap lowercase int:tolower RewriteMap vhost txt:/path/to/vhost.map # Now do the actual virtual host mapping # via a huge and complicated single rule: # # 1. make sure we don't map for common locations RewriteCond %{REQUEST_URI} !^/commonurl1/.* RewriteCond %{REQUEST_URI} !^/commonurl2/.* : RewriteCond %{REQUEST_URI} !^/commonurlN/.* # # 2. make sure we have a Host header, because # currently our approach only supports # virtual hosting through this header RewriteCond %{HTTP_HOST} !^$ # # 3. lowercase the hostname RewriteCond ${lowercase:%{HTTP_HOST}|NONE} ^(.+)$ # # 4. lookup this hostname in vhost.map and # remember it only when it is a path # (and not "NONE" from above) RewriteCond ${vhost:%1} ^(/.*)$ # # 5. finally we can map the URL to its docroot location # and remember the virtual host for logging puposes RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}] :
Access Restriction
Blocking of Robots
- Description:
- How can we block a really annoying robot from retrieving pages of a specific webarea? A
/robots.txtfile containing entries of the "Robot Exclusion Protocol" is typically not enough to get rid of such a robot.
- Solution:
- We use a ruleset which forbids the URLs of the webarea
/~quux/foo/arc/(perhaps a very deep directory indexed area where the robot traversal would create big server load). We have to make sure that we forbid access only to the particular robot, i.e. just forbidding the host where the robot runs is not enough. This would block users from this host, too. We accomplish this by also matching the User-Agent HTTP header information.
RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.* RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$ RewriteRule ^/~quux/foo/arc/.+ - [F]
Blocked Inline-Images
- Description:
- Assume we have under http://www.quux-corp.de/~quux/ some pages with inlined GIF graphics. These graphics are nice, so others directly incorporate them via hyperlinks to their pages. We don't like this practice because it adds useless traffic to our server.
- Solution:
- While we cannot 100% protect the images from inclusion, we can at least restrict the cases where the browser sends a HTTP Referer header.
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC] RewriteRule .*\.gif$ - [F]
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$ RewriteRule ^inlined-in-foo\.gif$ - [F]
Host Deny
- Description:
- How can we forbid a list of externally configured hosts from using our server?
- Solution:
- For Apache >= 1.3b6:
RewriteEngine on RewriteMap hosts-deny txt:/path/to/hosts.deny RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR] RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND RewriteRule ^/.* - [F]
For Apache <= 1.3b6:
RewriteEngine on RewriteMap hosts-deny txt:/path/to/hosts.deny RewriteRule ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1 RewriteRule !^NOT-FOUND/.* - [F] RewriteRule ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1 RewriteRule !^NOT-FOUND/.* - [F] RewriteRule ^NOT-FOUND/(.*)$ /$1
## ## hosts.deny ## ## ATTENTION! This is a map, not a list, even when we treat it as such. ## mod_rewrite parses it for key/value pairs, so at least a ## dummy value "-" must be present for each entry. ## 22.214.171.124 - bsdti1.sdm.de - 184.108.40.206 -
URL-Restricted Proxy
- Description:
- How can we restrict the proxy to allow access to a configurable set of internet sites only? The site list is extracted from a prepared bookmarks file.
- Solution:
- We first have to make sure mod_rewrite is below(!) mod_proxy in the
Configurationfile when compiling the Apache webserver (or in the
AddModulelist of
httpd.confin the case of dynamically loaded modules), as it must get called _before_ mod_proxy.
For simplicity, we generate the site list as a textfile map (but see the mod_rewrite documentation for a conversion script to DBM format). A typical Netscape bookmarks file can be converted to a list of sites with a shell script like this:
#!/bin/sh cat ${1:-~/.netscape/bookmarks.html} | tr -d '\015' | tr '[A-Z]' '[a-z]' | grep href=\" | sed -e '/href="file:/d;' -e '/href="news:/d;' \ -e 's|^.*href="[^:]*://\([^:/"]*\).*$|\1 OK|;' \ -e '/href="/s|^.*href="\([^:/"]*\).*$|\1 OK|;' | sort -u
We redirect the resulting output into a text file called
goodsites.txt. It now looks similar to this:
www.apache.org OK xml.apache.org OK jakarta.apache.org OK perl.apache.org OK ...
We reference this site file within the configuration for the
VirtualHostwhich is responsible for serving as a proxy (often not port 80, but 81, 8080 or 8008).
<VirtualHost *:8008> ... RewriteEngine On # Either use the (plaintext) allow list from goodsites.txt RewriteMap ProxyAllow txt:/usr/local/apache/conf/goodsites.txt # Or, for faster access, convert it to a DBM database: #RewriteMap ProxyAllow dbm:/usr/local/apache/conf/goodsites # Match lowercased hostnames RewriteMap lowercase int:tolower # Here we go: # 1) first lowercase the site name and strip off a :port suffix RewriteCond ${lowercase:%{HTTP_HOST}} ^([^:]*).*$ # 2) next look it up in the map file. # "%1" refers to the previous regex. # If the result is "OK", proxy access is granted. RewriteCond ${ProxyAllow:%1|DENY} !^OK$ [NC] # 3) Disallow proxy requests if the site was _not_ tagged "OK": RewriteRule ^proxy: - [F] ... </VirtualHost>
Proxy Deny
- Description:
- How can we forbid a certain host or even a user of a special host from using the Apache proxy?
- Solution:
- We first have to make sure mod_rewrite is below(!) mod_proxy in the
Configurationfile when compiling the Apache webserver. This way it gets called _before_ mod_proxy. Then we configure the following for a host-dependend deny...
RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$ RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
...and this one for a user@host-dependend deny:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$ RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
Special Authentication Variant
- Description:
- Sometimes a very special authentication is needed, for instance a authentication which checks for a set of explicitly configured users. Only these should receive access and without explicit prompting (which would occur when using the Basic Auth via mod_access).
- Solution:
- We use a list of rewrite conditions to exclude all except our friends:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^firstname.lastname@example.com\.com$ RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^firstname.lastname@example.com\.com$ RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^email@example.com\.com$ RewriteRule ^/~quux/only-for-friends/ - [F]
Referer-based Deflector
- Description:
- How can we program a flexible URL Deflector which acts on the "Referer" HTTP header and can be configured with as many referring pages as we like?
- Solution:
- Use the following really tricky ruleset...
RewriteMap deflector txt:/path/to/deflector.map RewriteCond %{HTTP_REFERER} !="" RewriteCond ${deflector:%{HTTP_REFERER}} ^-$ RewriteRule ^.* %{HTTP_REFERER} [R,L] RewriteCond %{HTTP_REFERER} !="" RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]
... in conjunction with a corresponding rewrite map:
## ## deflector.map ## http://www.badguys.com/bad/index.html - http://www.badguys.com/bad/index2.html - http://www.badguys.com/bad/index3.html http://somewhere.com/
This automatically redirects the request back to the referring page (when "-" is used as the value in the map) or to a specific URL (when an URL is specified in the map as the second argument).
External Rewriting Engine
- Description:
- A FAQ: How can we solve the FOO/BAR/QUUX/etc. problem? There seems no solution by the use of mod_rewrite...
- Solution:
- Use an external rewrite map, i.e. a program which acts like a rewrite map. It is run once on startup of Apache receives the requested URLs on STDIN and has to put the resulting (usually rewritten) URL on STDOUT (same order!).
RewriteEngine on RewriteMap quux-map prg:/path/to/map.quux.pl RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}
#!/path/to/perl # disable buffered I/O which would lead # to deadloops for the Apache server $| = 1; # read URLs one per line from stdin and # generate substitution URL on stdout while (<>) { s|^foo/|bar/|; print $_; }
This is a demonstration-only example and just rewrites all URLs
/~quux/bar/.... Actually you can program whatever you like. But notice that while such maps can be used also by an average user, only the system administrator can define it.
Apache HTTP Server Version 1.3


text:
top of page
Home > Erotic Art Gallery > Explicit Sex Art 1 > Explicit Sex Art 2 > Your lips on my tongue
Gallery quality Canvas print
Size 17"x24"
Signed by Samarel
Price: $185
Secure online ordering
Money back guarantee
Free Shipping
Each piece of artwork is printed on the finest quality artists' canvas, signed by the artist. Your Canvas print will be shipped rolled and packaged in a poster tube. This shipping method ensures that you receive the artwork undamaged. Please allow 2-3 weeks for shipping and handling. There might be some slight differences in the final print size. Special ordering for specific sizes is available. For any question - Contact Samarel.
bottom of page

subset: commoncrawl


text:
Login Now
Login with OTP
Register now for FREE
Forgot Password?
Move to high level of wellness !
Thanks for visiting Beyoung store... The most rewarding wellness store.
We take your privacy seriously.
Previous Order History
Congratulations !!!
You will get 20% discount on minimum purchase of Rs. 2000.00/- and shipping will be completely FREE.
Enjoy Shopping !
Enjoy Wellness !!
Save Money !!!
NoToDengu™ Pills[A]


text:
Similar Cases
LxWxD: 30.16" x 18.33" x 13.12"
LxWxD: 31.00" x 24.00" x 16.00"
LxWxD: 29.00" x 14.50" x 14.00"
LxWxD: 30.25" x 18.50" x 20.00"
Product Information
Ameripack is recognized worldwide for having the most durable, most innovative Rotationally Molded Shipping and Storage Containers. Ameripack offers the largest assortment of sizes available from any source. We will work closely with you to define, develop and provide the perfect solution to your on-going packing and storage requirements. All Roto-Molded Shipping and Storage Containers are produced to the rigorous specifications of the Airline Transportation Association and comply with the ATA 300 Category 1 specification for 100 trip applications. Roto-Molded shipping and Storage containers can be produced to be airtight and water tight. These containers also conform to the specifications of many Mil-Specifications and Federal standards.
Ameripacks innovative solutions like our patented, large plastic handles which make them easy to grab while wearing mop gloves, or our patented edge caster system that allows container stacking cannot be found with any of our competitors and makes Ameripack the #1 choice of rotationally molded containers by the US Military, Fire and Police, as well as throughout the commercial industry.


text:
No matter what your eye condition, or how you choose to view the world, there are now prescription lenses that meet your unique lifestyle and vision correction needs. Eyeglass lenses that change as the light changes, from clear indoors to dark outdoors. Bifocal lenses that provide multiple fields of vision. High-index lenses that are thinner and lighter than ever before. And progressive lenses that eliminate the traditional lines of multi-focal lenses. The point is, while eyeglass lenses are prescribed to correct all kinds of vision problems, prescription lenses have come a long way—offering you the opportunity to truly customize your eyeglasses and make a statement about how you choose to look at the world.
Eyeglass Basics | North San Jose – River Oaks Family Optometry


text:
Calendar of Events Submission - The Greater Wyalusing Chamber of Commerce
Welcome to the Calendar of Events submission system!
From here, you can submit your event for inclusion in our Calendar of Events.
After you enter your event information, it will be placed into a pending status. An email will be sent to the calendar editor. Once your event is reviewed and approved by the editor, it will become active in the calendar.


text:
Generic Alfenta Availability
Last updated on Nov 7, 2023.
Alfenta is a brand name of alfentanil, approved by the FDA in the following formulation(s):
ALFENTA (alfentanil hydrochloride - injectable;injection)
Has a generic version of Alfenta been approved?
Yes. The following products are equivalent to Alfenta:
ALFENTANIL (alfentanil hydrochloride injectable;injection)
Note: Fraudulent online pharmacies may attempt to sell an illegal generic version of Alfenta. These medications may be counterfeit and potentially unsafe. If you purchase medications online, be sure you are buying from a reputable and valid online pharmacy. Ask your health care provider for advice if you are unsure about the online purchase of any medication.
See also: Generic Drug FAQ.
More about Alfenta (alfentanil)
- Check interactions
- Compare alternatives
- Side effects
- Dosage information
- During pregnancy
- Drug class: Opioids (narcotic analgesics)
- Breastfeeding
Professional resources
Related treatment guides
|Drug Patent
|A drug patent is assigned by the U.S. Patent and Trademark Office and assigns exclusive legal right to the patent holder to protect the proprietary chemical formulation. The patent assigns exclusive legal right to the inventor or patent holder, and may include entities such as the drug brand name, trademark, product dosage form, ingredient formulation, or manufacturing process A patent usually expires 20 years from the date of filing, but can be variable based on many factors, including development of new formulations of the original chemical, and patent infringement litigation.
|Drug Exclusivity
|Exclusivity is the sole marketing rights granted by the FDA to a manufacturer upon the approval of a drug and may run simultaneously with a patent. Exclusivity periods can run from 180 days to seven years depending upon the circumstance of the exclusivity grant.
|A Reference Listed Drug (RLD) is an approved drug product to which new generic versions are compared to show that they are bioequivalent. A drug company seeking approval to market a generic equivalent must refer to the Reference Listed Drug in its Abbreviated New Drug Application (ANDA). By designating a single reference listed drug as the standard to which all generic versions must be shown to be bioequivalent, FDA hopes to avoid possible significant variations among generic drugs and their brand name counterpart.
|Injectable aqueous solutions and, in certain instances, intravenous non-aqueous solutions. It should be noted that even though injectable (parenteral) products under a specific listing may be evaluated as therapeutically equivalent, there may be important differences among the products in the general category, Injectable; Injection. For example, some injectable products that are rated therapeutically equivalent are labeled for different routes of administration. In addition, some products evaluated as therapeutically equivalent may have different preservatives or no preservatives at all. Injectable products available as dry powders for reconstitution, concentrated sterile solutions for dilution, or sterile solutions ready for injection are pharmaceutical alternative drug products. They are not rated as therapeutically equivalent (AP) to each other even if these pharmaceutical alternative drug products are designed to produce the same concentration prior to injection and are similarly labeled. Consistent with accepted professional practice, it is the responsibility of the prescriber, dispenser, or individual administering the product to be familiar with a product's labeling to assure that it is given only by the route(s) of administration stated in the labeling.
Further information
Always consult your healthcare provider to ensure the information displayed on this page applies to your personal circumstances.


text:
Regular Socks Elves
Choose a variant
Delivery before Christmas
Up to 100 days for returns.
Product code: GMRS108
- Material: 70% cotton, 28% polyamide and 2% elastane
- Brand: Dedoles
- Original design inspired by everything around us
- Comfortable fit
- Wash the socks at maximum temperature 40 °C
- Not recommended: tumble drying, dry cleaning or the use of bleach
- Designed in Slovakia, made in Turkey
Elves are mythical creatures with magical powers. Our Dedoles elves have one special power too, they bring joy and smile wherever you set foot.
Spread positive vibes all around you! These original Dedoles socks are designed to bring joy and fun to everyday life. They help you express your true self and provide perfect comfort for your feet. The ultimate gift for all your friends and family.
DHL GlobalMail$4.99Our goods are delivered by DHL GlobalMail with a standard, non-tracked service. Import duties and customs are responsibility of the receiver.
Delivery can be late due to current covid situation.
If the goods did not fit nor meet your expectations, you can easily return it within 100 days. You can either return the product and we will exchange it for another one (you don't pay any postage for the second delivery) or you can return the product and we will refund the money to your bank account.
We accept only unwashed and unworn goods with original labels for exchange/return. Due to hygienic reasons we do not accept underwear (trunks, shorts, briefs, etc.), swimwear, socks, face masks tried on.


text:
Free .catering Transfer & Long-Term Registration Discount
Catering is a key component in creating a memorable and fun for all events. .catering won't let your business, wedding or birthday guests hungry as it represents the best catering companies out there. If you are supplying food to public or private events and wish to be recognized online, choose .catering for your website.
|registration price
|renewal price
|transfer price
|1 year
|Register Now
|2 years
|Register Now
|3 years
|Register Now
|4 years
|Register Now
|5 years
|Register Now
|6 years
|Register Now
|7 years
|Register Now
|8 years
|Register Now
|9 years
|Register Now
|10 years
|Register Now
Get started with immediate activation or have your website transferred in less than an hour!
Cloak your identity and obtain a proxy contact information for the Whois lookup to display.
Add, remove or edit DNS records for your domains with just a few simple clicks.
Show how serious you are in what you do with a custom Nameservers tailored specifically to your domain.
Lock your .asia and other domains safely from unauthorized attempts to transfer them elsewhere.
Control your online presence with precision and show your customers only your unique brand.
Have your emails accessible from multiple email accounts on different platforms in an instant.
Get started with immediate activation or have your website transferred in less than an hour.
Performance that exceeds your expectations and features you are about to fall in love with
Quick and easy – no transfer fee. We will renew your domain for one year free of charge.
Up to 300% faster access to your files and databases compared to non-SSD hosting providers!
Distribute your content around the world, so it's closer to your visitors (speeding up your site).
The most popular and powerful web hosting control panel for easy point-and-click management of your hosting account.
Free daily and weekly backups of your data to keep you safe. When others charge for this, we don't!
Because there is no great hosting without great technical support that cares about your website.
Our migration experts provide fast managed transfers on all plans, including moving of all your files, databases and emails.
45 days money-back guarantee for Cloud Shared Hosting and 7 days for VPS/DS Servers.
FastComet has been exceptional and I couldn't be happier. They have helped me with several issues on my sites. Just off the top of my head they've helped me with email, site speed, addressing issues that have popped up on analytics and webmaster tools. I've been very pleased with their support.
The technical service was simply great and fast. Even too fast! I started working on my new website on my vacation time, during the Christmas time, and I was assisted on a weekend evening during that period. I thought it was crazy when the customer service answered on the chat me instantly!
I took advantage of your support and I must say, it is the perfect one. It is very fast, servers reliability is incredible and dedicated servers are setup and configured very quickly. Honestly, you are particularly good for small and big websites!
FastComet's service is the best I have seen of any host I have used. The technical staff are very knowledgeable and quick to respond. And they are patient, even when the problem was caused by something I did wrong. I haven't needed them much lately because my site has been created and things are running smoothly now, but it's great to know they are there to answer my questions.
FastComet never made me feel silly for asking questions and provided great resources to help me understand how to attract more people to my site. I was able to have complete creative control without being overwhelmed with too many question or options. Whenever I had a question or issue, I received a prompt reply with a solution! I can't say enough good things!
I've been with FastComet 5 months, and have already recommended it to three friends who are now using FastComet' service. They are very satisfied!
After the migration, we really experienced how well the support is – even when the questions considered our systems and not regarding the hosting itself. Therefore, after a short testing, we moved all of our projects to FastComet and we never regretted this decision.
We are really experiencing joy of God's blessing in our mission. Without our service, thousands of young people would not have found good education and hope for the future. We are grateful for the many volunteers and donors helping us in our mission. FastComet is one of them.
I have been SOO happy with FastComet. I am totally tech-unsavvy and the customer service that FastComet provides far exceeds my past service provider (on which I also paid double the price for monthly service!). As soon as anything goes wrong, or isn't working right, I know I can easily get my site fixed with their help.
A domain name is basically your address name on the web, or alternatively said the URL that people type in the browser to access your website. An example would be the domain name for our site is https://www.fastcomet.com/. Having a custom domain name gives your site the desired professional look, while also improving your brand identity, and helping visitors find you on the Internet.
Even if you do not have a website, it is not a bad idea to register your branded domain name when you are certain about it, before someone else beats you to the punch.
Of course! When registering a domain name, you are considered as the official domain name owner. At any time you can decide whether to switch registrar that suits your requirements better. There are many people that initially register their domain names with one web host and end up switching to another.
We offer a simple and straightforward transferring process, which ensures that your domain is transferred as quickly and effortlessly as possible. Besides the free perks that come with each domain registered with us, there are even more incentives to transfer your existing domain to FastComet:
However, your registered domain name has to meet some requirements. Follow our Domain Transfer step-by-step tutorial if you want to move over your domain. It's easy to get started and we provide all of the information you'll need to walk you through the process.
Anyone that registers a domain name is required by the domain name regulator ICANN (Internet Corporation for Assigned Names and Numbers) to create a public record of domain ownership and the personal contact information of the Registrant in the Whois Search Directory. The WHOIS listing is a database of all registered domains. It's searchable and available to everyone on the Internet. Without domain privacy (also referred to as WHOIS privacy protection), your entire contact information (address, phone number, name, etc.) is publicly available. Additionally, your domain name expirations, renewal and other essential data used for legal purposes will be shown. This means that hackers, telemarketers, and spammers will be able to access the addresses and phone numbers of any domain registrant.
Domain ID protection (aka Whois privacy) puts your personal data with that of your official domain registry under a cloak of invisibility and hides it from the Whois database, which is globally accessible, masking it with generic data.
This service masks some of your personal details through the use of automated access points. The GDPR Whois protection is what limits a potential spammer if they want to access your first or last name, email information, and phone number by using automated measures (a.k.a. Port 43 Access).
For an existing domain name, if any one of the Registrant, Admin, Tech and Billing contacts are confirmed as being from the EU, we would mask the WHOIS output. The masking is done using placeholder details in substitution of users' personal info.
Customers from all European Economic Area (EEA) countries get to choose whether to enable or disable their GDPR Protection. The GDPR Protection is what masks a customer's WHOIS information to comply with the GDPR requirements, from their Client Area. Nevertheless, GDPR Protection will be enabled by default for all EEA customers.
Keep note that some TLD registries often display customer WHOIS details. It's also important to know that the GDPR Protection will not be available for some new and existing TLD registrations. As of May 17, 2017, these TLDs are : .AU, .BR, .CA, .CN (2nd and 3rd level), .DE (2nd and 3rd level), .EC (2nd and 3rd level), .EU, .RU (2nd and 3rd level), .UK (2nd and 3rd level), .US, .ECO, .JOBS, .NGO/.ONG, .NYC and .TEL.
The personal data of all EEA (European Economic Area) customers is hidden under GDPR Protection by default. However, the Domain privacy (ID Protect) remains as an optional purchase for all EEA registrants. Keep note that the GDPR Protection will only mask EEA registrants' data. It won't replace any emails to the registrant.
The ID Protect continues to be beneficial for all customers that are interested in having emails forwarded to them (e.g., for those interested in sales opportunities domains, transfer requests, in addition to fielding other communications) without the public display of their personal data.


text:
What is CEREC® used for?
Inlay Restoration
Often, patients with amalgam fillings will exhibit amalgam breakdowns and damage to the tooth structure as recurrent decay creates stress fractures on the enamel. Unlike most laboratory-created crowns, CEREC® inlay restorations stabilize the integrity of the tooth. CEREC® materials ensure maximum bond strength and enhance appearance, resulting in your desired smile. CEREC® inlay restorations form a smooth, tooth-colored replacement of dental material lost to cavities. Using ultramodern CAD/CAM technology, CEREC® inlays mimic your tooth's color and structure exactly.
Onlay Restorations
Silver amalgam restorations regularly result in unsightly crowns and the necessity of replacement over time from recurrent decay. Rather than replace the old amalgam, CEREC® onlays are placed on the tooth to retain the original structure and create a more natural look. Onlays, or partial crowns, are more extensive than inlays, and cover the bumps on the tooth surface. The enamel-like material of CEREC® mimics the appearance and feel of real teeth.
Dental Crowns
Patients who lose fillings often need replacement crowns, which can take up to three appointments to fill in. CEREC®, however, mirrors the appearance and feel of a normal tooth and only requires one visit to install. Dental crowns, or tooth-shaped caps placed over teeth, restore the damaged tooth to its original shape, strength, size or appearance. CEREC® crowns preserve a healthy tooth structure while restoring your natural smile.
Feel Confident About Your Smile!If you're in need of restorative or cosmetic dental treatments, Drs. Veisman, Tam, Luk, Laing or Zheng and her team have the expertise to provide these services with the highest level of care.
Teeth Veneers
Teeth that have been repaired with compacted composite material often break down, resulting in chipped teeth. CEREC® veneers correct the incisal length and angle, restoring the tooth to its original appearance in only one visit. Teeth veneers, or thin laminates of tooth-colored porcelain, are bonded to the front of teeth, covering the front surface and resulting in an improved appearance. The dental veneers produced by CEREC® are custom-designed for each tooth to provide an exact match.
Multiple Restorations
In the past, patients with multiple failed restorations typically required several appointments to achieve a full restoration. With CEREC®, however, multiple inlays and onlays can be fabricated, bonded, polished and installed at once. CEREC® technology completes the multiple restorations in one visit, resulting in a beautiful smile in a fraction of the time.


text:
A very naive couple wants to test out swinging on Honolulu
First name: Marie-raymonde, Age: 22 yo, City: Honolulu (HI)
We are oriented towards sadomasochism. The best for me is when I am hooked up so that my husband can watch while you hurt me and I'll get off like crazy. Age is not important, but a good feeling is essential to have fun together. We just want a naughty man for sex. We suggest you meet us in the woods to find your way back. Finally, we're available on Friday. You can write a message, we will be happy to look at it. I hope to give you a date for a beautiful libertine encounter. Big kisses. Bye bye.
Looking for an open-minded woman in Tamarac for my very naughty wife
First name: Ena, Age: 19 yo, City: Tamarac (FL)
Hello everyone, I am a very charming and sexy woman of 19 years. I am Ena. We've been amateur naughty game players for a while. We're discovering new naughty things from time to time, lately it's exhibitionism. We can meet you outside. We can be free this weekend for this libertine rendezvous in Tamarac. I am only on this libertine site to discover otherlibertines. My boyfriend is totally on board with this approach. I'm looking for a hot guy with a big dick so my boyfriend can see him fuck me. If you want to write a comment, we will be happy to look at it. I hope to give you a date for a nice swingers' encounter. Big kisses. See you soon.
I'm a young, virgin girl in New Bern looking for my first hookup
First name: Waltraud, Age: 29 yo, City: New Bern (NC)
Welcome to my profile, I am a very hot woman who is married but cheating on her guy. I work as a waitress and it's not very exciting. Since I'm the hot type, I felt like looking for a guy. I am available on Saturday and rather in the morning. We can meet wherever you want. I love role-playing games. I would like a man who is inventing at this level to lead me in my fiction and take me into his universe and desires. I want a man who is good with women. Someone to practice swinging without taboos. To conclude, I am looking forward to finding your messages. I can't wait to have a steamy night with you. I'm sure we'll get along great during this naughty meeting. See you soon! Big kisses.
Looking for a hot 44-year-old wife who loves candaulism? Check out Sacramento
First name: Cyprienne, Age: 44 yo, City: Sacramento (CA)
We prefer a man of our age for this rendezvous between libertines. I'm a very playful woman, I need a real man to take pleasure in. Different practices are carried out in libertinism. We are fans of group sex and particularly voyeurism. There's no denying that kissing in a cave is one of our favorite pastimes. We are free this weekend for a libertine rendezvous in Sacramento. You can see me in a swingers club. To meet us, simply leave a comment. We only want to have fun between amateur pleasure-seekers.
Looking for a hot couple to have some fun with in a private club tonight Woodland
First name: Alicia, Age: 48 yo, City: Woodland (CA)
Hello all you naughty people, my name is Alicia and I am with a guy. I am 48 years old and my guy is 50 years old. We are registered on this libertine dating site because we are libertines. I don't think I have any physical criteria because it's just for a quick fuck... But on the other hand, I want a real man who can deliver. It's mostly important to me that my man is able to see another male make me orgasm. Since we work a lot, we prefer to see you on weekends and if possible at our home or in a hot club near Woodland. I love practicing candaulism because I enjoy having sex with another man while my husband watches. I'm extremely hot when I get it on and I especially love having my pussy eaten with delicate. Now that you understand what I want, you can leave me a comment. I'm sure I'll have a great time with you. I'm leaving. Kisses.
A sexy couple living in East Los Angeles for a night of sex at a swingers club
First name: Valerienne, Age: 42 yo, City: East Los Angeles (CA)
I am a woman who is in a civil partnership, my name is Valerienne and I am 42 years old and my friend is 40 years old. We are libertines. We love sadomasochism. The best is when I'm tied up so my guy can ogle me while you lick me and I'll have a blast. I can see you in town. I would add that I am not against having a date in an exhibition place on East Los Angeles. I'm looking for a cool, liberated guy who will make me have fun with my boyfriend because I am a very hot girl who loves having 2 cocks for herself. So we're looking to have a good time with another man. We are quite knowledgeable. We are waiting for your responses. Big kisses.
Looking for a mature woman without a man on Fishers
First name: Moisa, Age: 41 yo, City: Fishers (IN)
I absolutely love revealing myself in nature and having my picture taken. However, what really gets me going are the unexpected hookups in public places (garages, bathrooms, etc.), so be creative with your cruising in Fishers. Since I'm a cougar, I only want to sleep with a man who is younger than me. I just want to have some fun in a one night stand. I am available on Saturday and in the morning. We can meet in the city center. You can write me a small message proposing a one-time hookup. I'm only interested in young men. Take care.
Cougar seeking one night stand in a basement
First name: Arthika, Age: 37 yo, City: Midwest City (OK)
Hi, I'm a pretty girl who is married but I am unfaithful. I work as a teacher and it's not very exciting. I'm quite nymphomaniac, so I felt like looking for a libertine. I want a man who is rather hot and has a nice penis in order to give me lots of sensations as I am a difficult girl. I know how to get my hookups hot and bothered. I just want to have someone for a casual encounter because I love making love without limits with a stranger. I like a lot of different kinds of foreplay, so I need an experienced libertine. You can meet up in an unusual place for this future libertine plan. Otherwise I'm available during the day and on weekends. You can write a small comment to suggest a meeting between libertins for one night. I'm only looking for men who are younger than me. I kiss you.
My slutty girlfriend wants big dicks all night long
First name: Zaklina, Age: 39 yo, City: Troy (MI)
We've been amateur swingers for a while now. My boyfriend and I try new naughty experiences regularly, right now it's BDSM. We would like to invite you over for a date. Finally, we're available on the weekends. We want a guy the same age for this evening between libertines. As a very playful woman, I need a real man to give me orgasms together. Please contact us if you would like to have a threesome. We hope to read your comments. Kisses.
Beautiful woman with a guy for a threesome desire on Port Huron
First name: Jahina, Age: 35 yo, City: Port Huron (MI)
I agree to give you a date in town. I also agree to meet for a date in the woods near Port Huron. We want a man or couple without taboo for this fuck because we desire to fuck as much as possible!!! Mister must be strong, sorry but it's my fantasy these days. I am an amateur of candaulism because I love to have fun with another man but only under the watchful eye of my husband. I'm quite naughty when I fuck and I especially love it when someone teases me slowly. So, we're waiting for your proposals for this fuck meet. Looking forward to meeting you on Port Huron! Kisses! See you soon.
- Escorts Leeds
- 9092252916
- Los Angeles Escord
- Adult Search Escort Hackettstown, New Jersey
- Escort Taunton
- Adult Search Escort Tonganoxie, Kansas
- Adult Search Escort Stony Brook University, New York
- Escorts In Pensacola Fl
- Miami Scort
- Readingescorts
- Adult Search Escort Terrell Hills, Texas
- Adult Search Escort Socorro, New Mexico
- Adult Search Escort Bellmore, New York
- 646-705-3988
- Lady Escorts Detroit
- Escort In Braintree
- Rubratings Greenville
- Escort Kent
- Adult Search Escort Inglewood, California
- Adult Search Escort Oneida, New York


text:
|Kamagra jelly is applied for the treatment of erectile dysfunction in men and pulmonary arterial hypertension.
|Buy Now
|Buy Now
|Buy Now
|Buy Now
|Buy Now
|Buy Now
Common use
Sildenafil is the main component of Kamagra Jelly.
Sildenafil affects the response to sexual stimulation. It acts by enhancing smooth muscle relaxation using nitric oxide, a chemical that is normally released in response to sexual stimulation. This smooth muscle relaxation allows increased blood flow into certain areas of the penis, which leads to an erection.
Sildenafil is applied for the treatment of erectile dysfunction (impotence) in men and pulmonary arterial hypertension.
Sildenafil may also be used for other purposes not listed above.
Dosage and direction
Kamagra Jelly is taken, as needed, approximately 1 hour before sexual activity. Do not take Kamagra Jelly more then once a day.
A high fat meal may delay the time of the effect of this drug.
Try not to eat grapefruit or drink grapefruit juice while you are being treated with Sildenafil.
Before you start taking Sildenafil, tell your doctor or pharmacist if you are allergic to it; or if you have any other allergies.
Aged people may be more sensitive to the side effects of the drug.
Kamagra Jelly is contraindicated in patients taking another medicine to treat impotence or using a nitrate drug for chest pain or heart problems.
This medicine should not be taken by women and children as well as in patients with a known hypersensitivity to any component of the tablet.
Possible side effect
The most common side effects are headache, flushing, heartburn, stomach upset, nasal stuffiness, lightheadedness, dizziness or diarrhea.
A serious allergic reaction to this drug is very rare, but seek immediate medical help if it occurs.
Many people using this medicine do not have serious side effects.
In case you notice any side effects not listed above, contact your doctor or pharmacist.
Drug interaction
This drug should not be used with nitrates and recreational drugs called "poppers" containing amyl or butyl nitrite; alpha-blocker medications; other medications for impotence; high blood pressure medicines, etc.
Consult your doctor or pharmacist for more details.
Missed dose
Kamagra Jelly is used as needed, so you are unlikely to be on a dosing schedule.
If you think you have used too much of this medicine seek emergency medical attention right away. The symptoms of overdose usually include chest pain, nausea, irregular heartbeat, and feeling light-headed or fainting.
Store your medicines at room temperature between 68-77 degrees F (20-25 degrees C) away from light and moisture. Do not store them in the bathroom. Keep all drugs away from reach of children and pets.
We provide only general information about medications which does not cover all directions, possible drug integrations, or precautions. Information at the site cannot be used for self-treatment and self-diagnosis. Аnу specific instructions for a particular patient should be agreed with your health care adviser or doctor in charge of the case. We disclaim reliability of this information and mistakes it could contain. We are not responsible for any direct, indirect, special or other indirect damage as a result of any use of the information on this site and also for consequences of self-treatment.


text:
The dedicated staff at Otels want to help you with your lodging and travel needs... around the clock. Please enter your travel request, comment, or suggestion in the space below:
To make a new reservation or modify an existing reservation, please phone:
(+1) 800-641-1385 (within U.S. or Canada)
(+1) 949-930-9550 (worldwide)
OTELS is one of the largest families of hotel websites in the world, offering you a fast way to find a hotel. Open our websites & click around the world ... to reserve your next hotel.
Subscribe to our newsletter and stay up to date with the latest news and deals!
Top destinations in Europe
Things to do in Europe
Travel tips for Europe
2023 © Otels, Inc. ALL Rights Reserved.
Privacy Policy | Terms of Service


text:
Skip to Main Content
District Home
Select a School...
Select a School
A.C. Corcoran Elementary School
Academic Magnet High School
Allegro Charter School of Music
Angel Oak Elementary School
Ashley River Creative Arts Elementary School
Baptist Hill Middle High School
Belle Hall Elementary School
Buist Academy for Advanced Studies
Burke High School
C.E. Williams Middle School (North Campus)
C.E. Williams Middle School (South Campus)
Camp Road Middle School
Carolina Park Elementary School
CCSD School Choice
Charles Pinckney Elementary
Charleston County School Of The Arts
Charleston Development Academy Public Charter School
Charleston Progressive Academy
Chicora Elementary School
Cooper River Center for Advanced Studies
Daniel Jenkins Academy
Deer Park Middle School
Drayton Hall Elementary School
E.B. Ellington Elementary School
Early College High School
East Cooper Center for Advanced Studies
East Cooper Montessori Charter School
Edith L. Frierson Elementary School
Greg Mathis Charter High School
Harbor View Elementary School
Haut Gap Middle School
Hunley Park Elementary School
James Island Charter High School
James Island Elementary School
James Simons Montessori School
Jane Edwards Elementary School
Jennie Moore Elementary School
Jerry Zucker Middle School
Julian Mitchell Elementary School
Ladson Elementary School
Laing Middle School of Science and Technology
Lambs Elementary School
Laurel Hill Primary School
Liberty Hill Academy
Lucy Beckham High School
Malcolm C. Hursey Montessori School
Mamie P. Whitesides Elementary School
Mary Ford Early Learning & Family Center
Matilda F. Dunston Elementary School
Meeting Street Brentwood
Meeting Street - Burns
Memminger School Of Global Studies
Midland Park Primary School
Military Magnet Academy
Minnie Hughes Elementary School
Montessori Community School
Morningside Middle School
Moultrie Middle School
Mount Pleasant Academy
Mount Zion Elementary School
Murray-LaSaine Montessori School
North Charleston Creative Arts Elementary School
North Charleston Elementary School
North Charleston High School
Northwoods Middle School
Oakland Elementary School
Orange Grove Charter School
Pepperhill Elementary School
Pinehurst Elementary School
R.B. Stall High School
Sanders Clyde Elementary School
Septima P. Clark Academy
Simmons-Pinckney Middle School
Springfield Elementary School
St. Andrew's School of Math & Science
St. James-Santee Elementary-Middle School
St. John's High School
Stiles Point Elementary School
Stono Park Elementary School
Sullivan's Island Elementary School
Thomas C. Cario Middle School
Turning Point Academy
W.B. Goodwin Elementary School
Wando High School
West Ashley Center for Advanced Studies
West Ashley High School
Sign In
Search Our Site
What are you searching for?
About Us
State Report Card
Title 1
Mission & Vision
School Improvement Council
School Supply List
Uniform Policy
Grade Level Standards
Attendance Policy
Bus Routes
Title IX Coordinator
Safety Guidlines
Gator Matrix
Parent Handbook
Digital Resources
Gator Matrix
Staff Directory
W.B. Goodwin Elementary School
Everyday is a Great Day for Learning!
District Home
Translate Language
User Options
W.B. Goodwin Elementary School
Parents' Right to Know in Spanish
Title 1
Page Navigation
Content Page
Parents' Right to Know
Parents' Right to Know in Spanish
If you are having trouble viewing the document, you may
download the document.
Questions or Feedback?
Web Community Manager Privacy Policy (Updated)
Copyright © 2022 Finalsite - all rights reserved.


text:
2-Piece Slim Fit Simple Designed Suit DarkGreen
[Size Chart]
[Material & Care]
70% Polyester, 30% Viscose
Dry-clean recommended, hand-wash available but with cold water
[Style & Design]
Slim fit, peaked lapel, four buttons on the sleeve, button closure.
Flat front free length pants with extended waist strap, slanted side pockets.
Simple & elegant design concept and the type design combined classic suit culture with modern element. It's handsome and charming when you put on it.
1 * Blazer + 1 * Pants
Shipping Rates & Delivery Estimates
1. On our online store, free shipping is available for orders over $99.99! If your order amount is less than $99.99, then we'll charge $15 for the shipping fee.
2. The free shipping takes about 15-20 business days. The estimated delivery time of Express Shipping by DHL is 5-7 business days, which requires paying an extra $15.
Please note that our products all have a "2-5 business days" lead time.
Explanation of "Lead-time"
Our products all need a lead-time to make & prepare, and we ship the goods based on the Lead-time.
Lead-time refers to the preparation time before shipping, ensuring that customer can receive the product within the range of his preset time. Every order could not skip this step.
Generally, the time from you placed the order till you receive it is the lead-time plus shipping time.
You have 15 days to apply for a return since you receive the order. Please email our customer service email address: email@example.com
Please elaborate on the reason why you want to return the item, and then our after-sales department will contact you and send the return address.
Please make sure that the items you return are salable (see below), otherwise, it is not acceptable for us to provide exchanges or issue refunds for you.
1、The returned item should be unworn (aside from trying it on), unwashed, devoid of any stains, scuffs, tears, or weird smells, and needs to be in its original packaging with the manufacturer tags.
2、You are responsible for the return shipping fee if the return is caused by yourself. Please choose an economical/standard shipping method.
3、Please contact us for further questions, we will do our best to assist you.
We'll always inspect the products strictly before we ship out the products. In case of damages during the shipping, please contact us by email to inform us regarding the damaged products.
We will always be here to help you and solve problems together with you.
- Size Chart 1
- Size Chart 2


text: Buy From Amazon.comEtsy FindsGift GuidesHome Stuff 13 Cool Home Accessories For Photography Lovers Vintage/Polaroid Camera Pillows Buy it here Vintage Camera Bookends Buy it here TLR Camera screen printed glasses. Set of 4 Buy it here Umbra Candid 3-Piece Vintage Camera Wall Decor Set Buy it here Film Paper Towel Box Buy it here Vintage Camflash Nightlight Buy it here Vintage Camera Coin Bank Buy it here Photoshop Magnets Buy it here Camera Christmas Ornament Buy it here Oh Snap! Art Print Buy it here Recycled Film Roll Magnets Buy it here Ceramic Polaroid Coasters Buy it here Stitchtagram Instagram Pillows Buy it here More Products Buy From Amazon.comElectronics Jabra Elite 75t Earbuds – Alexa Enabled, True Wireless Earbuds with Charging Case True wireless earbuds that offer a great fit, great music and call experience. Jabra Elite 75t features 4-way microphones that filter out wind or any disruptive noises around you. With the Jabra Sound+ App, you can personalize your music sound with customizable equalizers that allow you to listen to your favorite music in a way that you will truly enjoy. The earbuds give you up to 7.5 hours of battery use, and the charging case gives you up to 28 hours of battery. Voice command is compatible with Alexa, Siri and Google Assistant. Buy it here Buy From Amazon.comCoffee & Tea Asobu Insulated Pour Over Coffee Maker Beautiful Pour-Over set from Asobu with insulated double-walled carafe that keeps your coffee hot for hours. The set includes the insulated carafe, which is available in a few finishes (copper, silver, red or black), reusable stainless steel micro mesh filter and a lid. A silicone heat-resistant grip on the carafe allows you to easy handle it in the brewing process. Buy it here AccessoriesBuy From Amazon.com BAGGU Standard Reusable Shopping Bag Set Baggu's best selling reusable bags are perfect for your daily grocery shopping or for carrying anything else. The bags are large enough to hold what 2 or 3 standard plastic bags would fit, and the handles are wide enough for you to carry over your shoulder. Available as a set of 3 bags or as individual bags. Buy it here Buy From Amazon.comElectronics Courant Catch: 2 Multi-Device Wireless Charger Courant's elegant wireless charger allows for fast 10w power (x2) for two devices. Thanks to its 5 coil charging surface, there are no dead zones on this charger, your device will charge wherever and however you place it. Courant has a premium design with Pebble-Grain Italian Leather, High-Grade Matte Aluminum Alloy and Durable Braided Nylon Cable. Available in 5 colors. Will work with any Qi-compatible device Buy it here Pages: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143More Products


text:
Animal experiences is a fun and exciting way for children to get up close and personal with animals from all over the world in an educational and safe environment. Children learn about the animals they are meeting and what makes them unique. We have a large variety of animals to choose from and you pick 8 to come to your special occasion or event!
*required field
We encourage you to post a comment if you find a professional that you feel strongly about. But first we would like to present an overview of some rules.
1. You must be 13 years old or older in order to post on this section of the website.
2. Please be aware that by submitting content to Hudson Valley Parent you grant us a nonexclusive, royalty-free, perpetual, transferable and irrevocable rights to use, reproduce, modify, adapt, translate, distribute, publish, create derivative works from and publicly display and perform such submissions in any media and to use the names included with the submission.
3. As a condition of your use of this special section of this website, you warrant that all information you supply is true, accurate and current. Please choose carefully the information you post on Hudson Valley Parent. You may not post any information that is unlawful, libelous, defamatory, obscene, pornographic or otherwise objectionable subject matter. Also there will be no soliciting, linking to objectionable material, or impersonating someone else.
Despite this prohibition, you may see information that is incorrect or objectionable. Although we assume no responsibility or liability for this material, we would appreciate it if you would please contact us if you become aware of this misuse of our site. Email our publisher at email@example.com.
4. Although Hudson Valley Parent has no obligation to screen, edit or monitor any of the posted content, Hudson Valley Parent reserves the right and has the absolute discretion to remove, screen or edit content without any notice.
5. Hudson Valley Parent takes no responsibility and assumes no liability for any content posted, stored or uploaded by you. Nor are we responsible for any mistakes, defamation, slander, libel, falsehoods, obscenity, you may encounter. As a provider of interactive services, Hudson Valley Parent is not liable for any statements provided by its users in any public form, personal home page or other interactive area.
Remember me
Along with your FREE membership, you will also be registered for HVParent's newsletters. As always, you can unsubscribe at any time.
FYI: Your privacy is important to us. We will not sell, rent, or give your information to anyone. At any point, you may modify your account settings.
Remember me
YES! I want my FREE membership to HVParent.com that includes my fully customizable home page where I decide what I want to see.


text:
Home Tags The Links Group Dubai Creek Seniors Open
Driven by the desire to keep abreast with the times, to be of use to our fellow citizens and all who are interested in what is happening in the world of golf in the UAE and beyond, wherever in the world they might be, we created the Golf.ae website.
It is our effort to advance understanding of environmental, political, religious, human rights, economic, democracy, scientific, and social justice issues, sport, etc. Be part of this process, share with us your stories, opinions, successes or problems.
We are an independent non-profit educational endeavor.